Skip to content
Draft
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
1 change: 1 addition & 0 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,7 @@ func main() {
OpenShiftMCPServerImage: imagesMap["openshift-mcp-server-image"],
DataverseExporterImage: imagesMap["dataverse-exporter-image"],
LightspeedCoreImage: imagesMap["lightspeed-core"],
OcpRagImage: imagesMap["ocp-rag-image"],
UseLCore: useLCore,
Namespace: namespace,
PrometheusAvailable: prometheusAvailable,
Expand Down
6 changes: 3 additions & 3 deletions internal/controller/appserver/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ func GenerateOLSDeployment(r reconciler.Reconciler, cr *olsv1alpha1.OLSConfig) (

// RAG volume
if len(cr.Spec.OLSConfig.RAG) > 0 {
ragVolume := generateRAGVolume()
ragVolume := utils.GenerateRAGVolume()
volumes = append(volumes, ragVolume)
}

Expand All @@ -313,7 +313,7 @@ func GenerateOLSDeployment(r reconciler.Reconciler, cr *olsv1alpha1.OLSConfig) (
)

if len(cr.Spec.OLSConfig.RAG) > 0 {
ragVolumeMounts := generateRAGVolumeMount()
ragVolumeMounts := utils.GenerateRAGVolumeMount()
volumeMounts = append(volumeMounts, ragVolumeMounts)
}

Expand Down Expand Up @@ -348,7 +348,7 @@ func GenerateOLSDeployment(r reconciler.Reconciler, cr *olsv1alpha1.OLSConfig) (

initContainers := []corev1.Container{}
if len(cr.Spec.OLSConfig.RAG) > 0 {
ragInitContainers := GenerateRAGInitContainers(cr)
ragInitContainers := utils.GenerateRAGInitContainers(cr)
initContainers = append(initContainers, ragInitContainers...)
}

Expand Down
47 changes: 0 additions & 47 deletions internal/controller/appserver/rag.go

This file was deleted.

45 changes: 14 additions & 31 deletions internal/controller/lcore/assets_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@ func TestBuildLlamaStackYAML_SupportedProvider(t *testing.T) {
}

// Build the YAML
ctx := context.Background()
yamlOutput, err := buildLlamaStackYAML(nil, ctx, cr)
yamlOutput, err := buildLlamaStackYAML(createTestReconciler(), context.Background(), cr)
if err != nil {
t.Fatalf("buildLlamaStackYAML returned error for supported provider: %v", err)
}
Expand Down Expand Up @@ -89,8 +88,7 @@ func TestBuildLlamaStackYAML_UnsupportedProvider(t *testing.T) {
}

// Build the YAML - should return error
ctx := context.Background()
yamlOutput, err := buildLlamaStackYAML(nil, ctx, cr)
yamlOutput, err := buildLlamaStackYAML(createTestReconciler(), context.Background(), cr)

// Verify error is returned
if err == nil {
Expand All @@ -104,10 +102,10 @@ func TestBuildLlamaStackYAML_UnsupportedProvider(t *testing.T) {
}
if err.Error() != "" && len(err.Error()) > 0 {
// Check if error message contains expected text
if !contains(err.Error(), expectedErrMsg) {
if !strings.Contains(err.Error(), expectedErrMsg) {
t.Errorf("Error message '%s' doesn't contain expected text '%s'", err.Error(), expectedErrMsg)
}
if !contains(err.Error(), providerType) {
if !strings.Contains(err.Error(), providerType) {
t.Errorf("Error message '%s' doesn't mention provider type '%s'", err.Error(), providerType)
}
}
Expand Down Expand Up @@ -142,8 +140,7 @@ func TestBuildLlamaStackYAML_OpenAICompatibleProviders(t *testing.T) {
}

// Build the YAML - should succeed
ctx := context.Background()
yamlOutput, err := buildLlamaStackYAML(nil, ctx, cr)
yamlOutput, err := buildLlamaStackYAML(createTestReconciler(), context.Background(), cr)

// Verify no error is returned
if err != nil {
Expand Down Expand Up @@ -262,8 +259,7 @@ func TestBuildLlamaStackYAML_AzureProvider(t *testing.T) {
}

// Build the YAML
ctx := context.Background()
yamlOutput, err := buildLlamaStackYAML(testReconciler, ctx, cr)
yamlOutput, err := buildLlamaStackYAML(testReconciler, context.Background(), cr)
if err != nil {
t.Fatalf("buildLlamaStackYAML returned error for Azure provider: %v", err)
}
Expand Down Expand Up @@ -344,24 +340,7 @@ func TestBuildLlamaStackYAML_AzureProvider(t *testing.T) {
t.Logf("Successfully validated Llama Stack YAML with Azure provider (%d bytes)", len(yamlOutput))
}

// Helper function to check if a string contains a substring
func contains(s, substr string) bool {
return len(s) >= len(substr) && (s == substr || len(s) > len(substr) && findSubstring(s, substr))
}

func findSubstring(s, substr string) bool {
for i := 0; i <= len(s)-len(substr); i++ {
if s[i:i+len(substr)] == substr {
return true
}
}
return false
}

func TestBuildLCoreConfigYAML(t *testing.T) {
// Use a proper CR from test fixtures instead of nil
cr := utils.GetDefaultOLSConfigCR()

func createTestReconciler() *utils.TestReconciler {
// Create a fake client and reconciler for the test
scheme := runtime.NewScheme()
_ = olsv1alpha1.AddToScheme(scheme)
Expand All @@ -370,15 +349,19 @@ func TestBuildLCoreConfigYAML(t *testing.T) {
WithScheme(scheme).
Build()
logger := zap.New(zap.UseDevMode(true))
testReconciler := utils.NewTestReconciler(
return utils.NewTestReconciler(
fakeClient,
logger,
scheme,
"test-namespace",
)
}

func TestBuildLCoreConfigYAML(t *testing.T) {
// Use a proper CR from test fixtures instead of nil
cr := utils.GetDefaultOLSConfigCR()

ctx := context.Background()
yamlOutput, err := buildLCoreConfigYAML(testReconciler, ctx, cr)
yamlOutput, err := buildLCoreConfigYAML(createTestReconciler(), context.Background(), cr)
if err != nil {
t.Fatalf("buildLCoreConfigYAML returned error: %v", err)
}
Expand Down
65 changes: 41 additions & 24 deletions internal/controller/lcore/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -374,23 +374,47 @@ func buildLlamaStackToolRuntime(_ reconciler.Reconciler, _ *olsv1alpha1.OLSConfi
}
}

func buildLlamaStackVectorDB(_ reconciler.Reconciler, _ *olsv1alpha1.OLSConfig) []interface{} {
return []interface{}{
map[string]interface{}{
"provider_id": "faiss",
func buildLlamaStackVectorIO(r reconciler.Reconciler, cr *olsv1alpha1.OLSConfig) []interface{} {
vectorIOs := []interface{}{}
// Use RAG configuration from OLSConfig if available
if len(cr.Spec.OLSConfig.RAG) > 0 {
for _, rag := range cr.Spec.OLSConfig.RAG {
id := "byok_rag_" + sanitizeID(rag.Image)
vectorIOs = append(vectorIOs, map[string]interface{}{
"provider_id": id,
"provider_type": "inline::faiss",
"config": map[string]interface{}{
"kvstore": map[string]interface{}{
"db_path": "/rag-data/" + id + "/faiss_store.db",
"type": "kv_sqlight",
},
"persistence": map[string]interface{}{
"backend": "kv_default",
"namespace": "vector_io::faiss",
},
},
})
}
}
if !cr.Spec.OLSConfig.ByokRAGOnly {
// OCP RAG database
vectorIOs = append(vectorIOs, map[string]interface{}{
"provider_id": "ocp-rag",
"provider_type": "inline::faiss",
"config": map[string]interface{}{
"kvstore": map[string]interface{}{
"backend": "sql_default",
"table_name": "vector_store",
"db_path": "/rag-data/ocp/vector_db/ocp_product_docs/" + r.GetOpenShiftMajor() + "." + r.GetOpenshiftMinor() + "/faiss_store.db",
"type": "kv_sqlight",
},
"persistence": map[string]interface{}{
"backend": "kv_default",
"namespace": "vector_persistence",
"namespace": "vector_io::faiss",
},
},
},
})
}

return vectorIOs
}

func buildLlamaStackServerConfig(_ reconciler.Reconciler, _ *olsv1alpha1.OLSConfig) map[string]interface{} {
Expand Down Expand Up @@ -428,26 +452,19 @@ func buildLlamaStackVectorDBs(_ reconciler.Reconciler, cr *olsv1alpha1.OLSConfig
vectorDB := map[string]interface{}{
"embedding_model": "sentence-transformers/all-mpnet-base-v2",
"embedding_dimension": 768,
"provider_id": "faiss",
"provider_id": "byok_rag_" + sanitizeID(rag.Image),
"vector_db_id": "byok_rag_" + sanitizeID(rag.Image),
}

// Use IndexID if specified, otherwise generate a default
if rag.IndexID != "" {
vectorDB["vector_db_id"] = rag.IndexID
} else {
// Generate a simple ID from the image name
vectorDB["vector_db_id"] = "rag_" + sanitizeID(rag.Image)
}

vectorDBs = append(vectorDBs, vectorDB)
}
} else {
// Default fallback if no RAG configured
}
if !cr.Spec.OLSConfig.ByokRAGOnly {
// OCP RAG database
vectorDBs = append(vectorDBs, map[string]interface{}{
"vector_db_id": "my_knowledge_base",
"vector_db_id": "ocp-rag",
"embedding_model": "sentence-transformers/all-mpnet-base-v2",
"embedding_dimension": 768,
"provider_id": "faiss",
"provider_id": "ocp-rag",
})
}

Expand Down Expand Up @@ -478,7 +495,7 @@ func buildLlamaStackModels(_ reconciler.Reconciler, cr *olsv1alpha1.OLSConfig) [
"model_id": "sentence-transformers/all-mpnet-base-v2",
"model_type": "embedding",
"provider_id": "sentence-transformers",
"provider_model_id": "sentence-transformers/all-mpnet-base-v2",
"provider_model_id": "/rag-data/ocp/embeddings_model",
"metadata": map[string]interface{}{
"embedding_dimension": 768,
},
Expand Down Expand Up @@ -595,7 +612,7 @@ func buildLlamaStackYAML(r reconciler.Reconciler, ctx context.Context, cr *olsv1
"safety": buildLlamaStackSafety(r, cr), // Required by agents provider
// "telemetry": buildLlamaStackTelemetry(r, cr), // Telemetry and tracing
"tool_runtime": buildLlamaStackToolRuntime(r, cr), // Required for RAG
"vector_io": buildLlamaStackVectorDB(r, cr), // Required for RAG
"vector_io": buildLlamaStackVectorIO(r, cr), // Required for RAG
}

// Add top-level fields
Expand Down
19 changes: 18 additions & 1 deletion internal/controller/lcore/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,9 @@ func GenerateLCoreDeployment(r reconciler.Reconciler, cr *olsv1alpha1.OLSConfig)
// PostgreSQL CA ConfigMap volume (for TLS certificate verification)
volumes = append(volumes, utils.GetPostgresCAConfigVolume())

// RAG volume
volumes = append(volumes, utils.GenerateRAGVolume())

// Add external TLS secret if provided by user
var tlsVolumeMounts []corev1.VolumeMount
if cr.Spec.OLSConfig.TLSConfig != nil && cr.Spec.OLSConfig.TLSConfig.KeyCertSecretRef.Name != "" {
Expand Down Expand Up @@ -318,6 +321,9 @@ func GenerateLCoreDeployment(r reconciler.Reconciler, cr *olsv1alpha1.OLSConfig)
utils.GetPostgresCAVolumeMount("/etc/certs/postgres-ca"),
}

// RAG volume mount
llamaStackVolumeMounts = append(llamaStackVolumeMounts, utils.GenerateRAGVolumeMount())

// User provided CA certificates - create both volumes and volume mounts in single pass
_ = utils.ForEachExternalConfigMap(cr, func(name, source string) error {
var volumeName, llamaStackMountPath string
Expand Down Expand Up @@ -526,6 +532,16 @@ func GenerateLCoreDeployment(r reconciler.Reconciler, cr *olsv1alpha1.OLSConfig)
}
lightspeedStackContainer.Resources = *lightspeedStackResources

initContainers := []corev1.Container{}
ocpRagDirName := "ocp"
ocpRagDir := path.Join(utils.RAGVolumeMountPath, ocpRagDirName)
initContainers = append(initContainers, utils.GenerateRAGInitContainer(ocpRagDirName, r.GetOcpRagImage(), ocpRagDir, cr))

if len(cr.Spec.OLSConfig.RAG) > 0 {
ragInitContainers := utils.GenerateRAGInitContainers(cr)
initContainers = append(initContainers, ragInitContainers...)
}

deployment := appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "lightspeed-stack-deployment",
Expand All @@ -552,7 +568,8 @@ func GenerateLCoreDeployment(r reconciler.Reconciler, cr *olsv1alpha1.OLSConfig)
llamaStackContainer,
lightspeedStackContainer,
},
Volumes: volumes,
Volumes: volumes,
InitContainers: initContainers,
},
},
RevisionHistoryLimit: &revisionHistoryLimit,
Expand Down
Loading