Skip to content
Merged
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
6 changes: 3 additions & 3 deletions api/v1beta1/openstacklightspeed_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,13 @@ const (
// May change at any time without backward compatibility.
//
// Supported fields:
// - featureFlags: list of experimental feature flags to enable (e.g. ["okp"])
// - featureFlags: list of experimental feature flags to enable
// - okpChunkFilterQuery: Solr filter query for OKP searches (default: version-aware query combining detected OpenStack and OCP versions)
// - okpRagOnly: when true, only OKP is used as a RAG source (default: false)
// - okpRagOnly: when true, only OKP is used as a RAG source (default: true)
type DevSpec struct {
FeatureFlags []string `json:"featureFlags,omitempty"`
OKPChunkFilterQuery string `json:"okpChunkFilterQuery,omitempty"`
OKPRagOnly bool `json:"okpRagOnly,omitempty"`
OKPRagOnly *bool `json:"okpRagOnly,omitempty"`
}

// OKPSpec defines configuration for the Offline Knowledge Portal (OKP).
Expand Down
5 changes: 5 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.

7 changes: 0 additions & 7 deletions internal/controller/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (
"encoding/json"
"errors"
"fmt"
"slices"
"strings"

common_helper "github.com/openstack-k8s-operators/lib-common/modules/common/helper"
Expand Down Expand Up @@ -142,12 +141,6 @@ func parseDevConfig(instance *apiv1beta1.OpenStackLightspeed) (apiv1beta1.DevSpe
return config, nil
}

// isOKPEnabled returns true if the "okp" feature flag is present in the dev config.
func isOKPEnabled(instance *apiv1beta1.OpenStackLightspeed) bool {
config, _ := parseDevConfig(instance)
return slices.Contains(config.FeatureFlags, "okp")
}

// getOKPChunkFilterQuery returns the chunk filter query from the dev config, or a version-aware default.
func getOKPChunkFilterQuery(ctx context.Context, h *common_helper.Helper, instance *apiv1beta1.OpenStackLightspeed) string {
config, _ := parseDevConfig(instance)
Expand Down
2 changes: 0 additions & 2 deletions internal/controller/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,6 @@ var (
// OKP Errors
ErrCreateOKPDeployment = errors.New("failed to create OKP deployment")
ErrCreateOKPService = errors.New("failed to create OKP service")
ErrDeleteOKPDeployment = errors.New("failed to delete OKP deployment")
ErrDeleteOKPService = errors.New("failed to delete OKP service")

// Postgres Errors
ErrCreatePostgresDeployment = errors.New("failed to create Postgres deployment")
Expand Down
10 changes: 2 additions & 8 deletions internal/controller/lcore_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,12 +220,8 @@ func buildOKPConfig(ctx context.Context, h *common_helper.Helper, instance *apiv
// buildLCoreConfigYAML assembles the complete Lightspeed Core Service configuration and converts to YAML.
// NOTE: MCP servers, quota handlers, and tools approval features are disabled for OpenStack Lightspeed.
func buildLCoreConfigYAML(ctx context.Context, h *common_helper.Helper, instance *apiv1beta1.OpenStackLightspeed) (string, error) {
okpEnabled := isOKPEnabled(instance)

ragInline := []interface{}{}
if okpEnabled {
ragInline = append(ragInline, "okp")
}
ragInline := []interface{}{"okp"}
ragConfig := map[string]interface{}{
"inline": ragInline,
}
Expand All @@ -245,9 +241,7 @@ func buildLCoreConfigYAML(ctx context.Context, h *common_helper.Helper, instance
"rag": ragConfig,
}

if okpEnabled {
config["okp"] = buildOKPConfig(ctx, h, instance)
}
config["okp"] = buildOKPConfig(ctx, h, instance)

// Convert to YAML
yamlBytes, err := yaml.Marshal(config)
Expand Down
26 changes: 10 additions & 16 deletions internal/controller/lcore_deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,9 +277,7 @@ func buildInitContainers(
"--enable-ocp-rag", strconv.FormatBool(instance.Spec.EnableOCPRAG),
"--ocp-version", ocp_version,
}
if isOKPEnabled(instance) {
cmd = append(cmd, "--enable-okp")
}
cmd = append(cmd, "--enable-okp")
return cmd
}(),
SecurityContext: securityContext,
Expand All @@ -304,7 +302,7 @@ func buildInitContainers(
"--lightspeed-stack-path", LightspeedStackInitContainerMountPath,
}
devConfig, _ := parseDevConfig(instance)
if devConfig.OKPRagOnly {
if devConfig.OKPRagOnly == nil || *devConfig.OKPRagOnly {
configBuildCmd = append(configBuildCmd, "--disable-rag-entries")
}

Expand Down Expand Up @@ -609,12 +607,10 @@ func buildLlamaStackEnvVars(h *common_helper.Helper, ctx context.Context, instan
Value: VectorDBVolumeMountPath,
})

if isOKPEnabled(instance) {
envVars = append(envVars, corev1.EnvVar{
Name: "RH_SERVER_OKP",
Value: fmt.Sprintf("http://%s.%s.svc:%d", OKPServiceName, instance.GetNamespace(), OKPServicePort),
})
}
envVars = append(envVars, corev1.EnvVar{
Name: "RH_SERVER_OKP",
Value: fmt.Sprintf("http://%s.%s.svc:%d", OKPServiceName, instance.GetNamespace(), OKPServicePort),
})

return envVars, nil
}
Expand Down Expand Up @@ -643,12 +639,10 @@ func buildLightspeedStackEnvVars(instance *apiv1beta1.OpenStackLightspeed) []cor
},
buildPostgresPasswordEnvVar(),
}
if isOKPEnabled(instance) {
envVars = append(envVars, corev1.EnvVar{
Name: "RH_SERVER_OKP",
Value: fmt.Sprintf("http://%s.%s.svc:%d", OKPServiceName, instance.GetNamespace(), OKPServicePort),
})
}
envVars = append(envVars, corev1.EnvVar{
Name: "RH_SERVER_OKP",
Value: fmt.Sprintf("http://%s.%s.svc:%d", OKPServiceName, instance.GetNamespace(), OKPServicePort),
})
return envVars
}

Expand Down
41 changes: 16 additions & 25 deletions internal/controller/llama_stack_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,9 +256,7 @@ func buildLlamaStackVectorDB(_ *common_helper.Helper, _ *apiv1beta1.OpenStackLig

func buildLlamaStackVectorIO(h *common_helper.Helper, instance *apiv1beta1.OpenStackLightspeed, chunkFilterQuery string) []interface{} {
providers := buildLlamaStackVectorDB(h, instance)
if isOKPEnabled(instance) {
providers = append(providers, buildOKPVectorIOProvider(chunkFilterQuery))
}
providers = append(providers, buildOKPVectorIOProvider(chunkFilterQuery))
return providers
}

Expand Down Expand Up @@ -378,32 +376,28 @@ func buildLlamaStackModels(_ *common_helper.Helper, instance *apiv1beta1.OpenSta
}
}

if isOKPEnabled(instance) {
models = append(models, map[string]interface{}{
"model_id": "solr_embedding",
"model_type": "embedding",
"provider_id": "sentence-transformers",
"provider_model_id": OKPEmbeddingModelMountPath,
"metadata": map[string]interface{}{
"embedding_dimension": 384,
},
})
}
models = append(models, map[string]interface{}{
"model_id": "solr_embedding",
"model_type": "embedding",
"provider_id": "sentence-transformers",
"provider_model_id": OKPEmbeddingModelMountPath,
"metadata": map[string]interface{}{
"embedding_dimension": 384,
},
})

return models
}

func buildLlamaStackVectorStores(_ *common_helper.Helper, instance *apiv1beta1.OpenStackLightspeed) []interface{} {
stores := []interface{}{}
if isOKPEnabled(instance) {
stores = append(stores, map[string]interface{}{
func buildLlamaStackVectorStores(_ *common_helper.Helper, _ *apiv1beta1.OpenStackLightspeed) []interface{} {
return []interface{}{
map[string]interface{}{
"vector_store_id": "portal-rag",
"provider_id": "okp_solr",
"embedding_dimension": 384,
"embedding_model": "sentence-transformers/" + OKPEmbeddingModelMountPath,
})
},
}
return stores
}

func buildLlamaStackToolGroups(_ *common_helper.Helper, _ *apiv1beta1.OpenStackLightspeed) []interface{} {
Expand All @@ -426,11 +420,8 @@ func buildLlamaStackYAML(h *common_helper.Helper, ctx context.Context, instance
return "", fmt.Errorf("failed to build inference providers: %w", err)
}

okpChunkFilterQuery := ""
if isOKPEnabled(instance) {
config["external_providers_dir"] = ExternalProvidersDir
okpChunkFilterQuery = getOKPChunkFilterQuery(ctx, h, instance)
}
config["external_providers_dir"] = ExternalProvidersDir
okpChunkFilterQuery := getOKPChunkFilterQuery(ctx, h, instance)

// Build providers map - only include providers for enabled APIs
config["providers"] = map[string]interface{}{
Expand Down
7 changes: 6 additions & 1 deletion internal/controller/llama_stack_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,15 @@ var _ = Describe("Llama Stack config", func() {
instance := getOpenStackLightspeedProvidersInstance(provider)
modelsConfig := buildLlamaStackModels(nil, instance)

Expect(modelsConfig).To(HaveLen(1))
Expect(modelsConfig).To(HaveLen(2))

modelConfig := modelsConfig[0].(map[string]interface{})
checkModelCommonConfig(modelConfig, instance)

okpModel := modelsConfig[1].(map[string]interface{})
Expect(okpModel["model_id"]).To(Equal("solr_embedding"))
Expect(okpModel["model_type"]).To(Equal("embedding"))
Expect(okpModel["provider_id"]).To(Equal("sentence-transformers"))
},
Entry("for openai", OpenAIProviderName),
Entry("for gemini", GeminiProviderName),
Expand Down
28 changes: 0 additions & 28 deletions internal/controller/okp_reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,49 +24,21 @@ import (
apiv1beta1 "github.com/openstack-k8s-operators/lightspeed-operator/api/v1beta1"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
)

// ReconcileOKPDeployment reconciles the OKP Deployment and Service.
// When OKP is disabled, it cleans up existing resources.
func ReconcileOKPDeployment(h *common_helper.Helper, ctx context.Context, instance *apiv1beta1.OpenStackLightspeed) error {
if !isOKPEnabled(instance) {
return cleanupOKPResources(h, ctx)
}

tasks := []ReconcileTask{
{Name: "OKPDeployment", Task: reconcileOKPDeployment},
{Name: "OKPService", Task: reconcileOKPService},
}
return ReconcileTasksFailFast(h, ctx, instance, tasks)
}

func cleanupOKPResources(h *common_helper.Helper, ctx context.Context) error {
Comment thread
umago marked this conversation as resolved.
logger := h.GetLogger()
ns := h.GetBeforeObject().GetNamespace()

deploy := &appsv1.Deployment{}
deploy.Name = OKPDeploymentName
deploy.Namespace = ns
if err := h.GetClient().Delete(ctx, deploy); err != nil && !errors.IsNotFound(err) {
return fmt.Errorf("%w: %v", ErrDeleteOKPDeployment, err)
}

svc := &corev1.Service{}
svc.Name = OKPServiceName
svc.Namespace = ns
if err := h.GetClient().Delete(ctx, svc); err != nil && !errors.IsNotFound(err) {
return fmt.Errorf("%w: %v", ErrDeleteOKPService, err)
}

logger.Info("OKP resources cleaned up")
return nil
}

func reconcileOKPDeployment(h *common_helper.Helper, ctx context.Context, instance *apiv1beta1.OpenStackLightspeed) error {
logger := h.GetLogger()

Expand Down
97 changes: 0 additions & 97 deletions test/kuttl/common/expected-configs/lightspeed-stack-okp.yaml

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,13 @@ llama_stack:
url: http://localhost:8321
use_as_library_client: false
name: Lightspeed Core Service (LCS)
okp:
chunk_filter_query: product:(*openstack* OR *openshift*)
offline: true
rhokp_url: ${env.RH_SERVER_OKP}
rag:
inline:
- vs_UUID
- okp
service:
access_log: true
auth_enabled: true
Expand Down
Loading
Loading