@@ -29,11 +29,7 @@ import (
2929 _ "embed"
3030
3131 common_helper "github.com/openstack-k8s-operators/lib-common/modules/common/helper"
32- k8s_errors "k8s.io/apimachinery/pkg/api/errors"
3332 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
34- uns "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
35- "k8s.io/apimachinery/pkg/runtime/schema"
36- "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
3733)
3834
3935const (
@@ -57,258 +53,6 @@ const (
5753 OLSConfigName = "cluster"
5854)
5955
60- // systemPrompt - system prompt tailored to the needs of OpenStack Lightspeed. It overwrites the default OLS prompt.
61- //
62- //go:embed system_prompt.txt
63- var systemPrompt string
64-
65- // GetSystemPrompt returns the OpenStackLightspeed system prompt
66- func GetSystemPrompt () string {
67- return systemPrompt
68- }
69-
70- // RemoveOLSConfig attempts to remove the OLSConfig custom resource if it exists
71- // and is managed by the given OpenStackLightspeed instance. It first fetches the OLSConfig,
72- // checks whether the current OpenStackLightspeed instance is the owner (via label check),
73- // and if so, removes the finalizer and deletes the OLSConfig resource.
74- // Returns (true, nil) if the OLSConfig is not found (indicating it has already been deleted).
75- // Returns (true, nil) if the resource was deleted successfully, or (false, error) if any error occurs.
76- func RemoveOLSConfig (
77- ctx context.Context ,
78- helper * common_helper.Helper ,
79- instance * apiv1beta1.OpenStackLightspeed ,
80- ) (bool , error ) {
81- olsConfig , err := GetOLSConfig (ctx , helper )
82- if err != nil && ! k8s_errors .IsNotFound (err ) {
83- return false , err
84- } else if err != nil && k8s_errors .IsNotFound (err ) {
85- return true , nil
86- }
87-
88- _ , err = controllerutil .CreateOrPatch (ctx , helper .GetClient (), & olsConfig , func () error {
89- ownerLabel := olsConfig .GetLabels ()[OpenStackLightspeedOwnerIDLabel ]
90- isInstanceOwnedOLSConfig := ownerLabel == string (instance .GetObjectMeta ().GetUID ())
91-
92- if ownerLabel == "" || ! isInstanceOwnedOLSConfig {
93- helper .GetLogger ().Info ("Skipping OLSConfig deletion as it is not managed by the OpenStackLightspeed instance" )
94- return nil
95- }
96-
97- if ok := controllerutil .RemoveFinalizer (& olsConfig , helper .GetFinalizer ()); ! ok {
98- return fmt .Errorf ("remove finalizer failed" )
99- }
100-
101- return nil
102- })
103- if err != nil {
104- return false , err
105- }
106-
107- err = helper .GetClient ().Delete (ctx , & olsConfig )
108- if err != nil {
109- return false , err
110- }
111-
112- _ , err = GetOLSConfig (ctx , helper )
113- if err != nil && k8s_errors .IsNotFound (err ) {
114- return true , nil
115- } else if err != nil {
116- return false , err
117- }
118-
119- return false , nil
120- }
121-
122- // GetOLSConfig returns OLSConfig if there is one present in the cluster.
123- func GetOLSConfig (ctx context.Context , helper * common_helper.Helper ) (uns.Unstructured , error ) {
124- OLSConfigGVR := schema.GroupVersionResource {
125- Group : "ols.openshift.io" ,
126- Version : "v1alpha1" ,
127- Resource : "olsconfigs" ,
128- }
129-
130- OLSConfigList := & uns.UnstructuredList {}
131- OLSConfigList .SetGroupVersionKind (OLSConfigGVR .GroupVersion ().WithKind ("OLSConfig" ))
132- err := helper .GetClient ().List (ctx , OLSConfigList )
133- if err != nil {
134- return uns.Unstructured {}, err
135- }
136-
137- if len (OLSConfigList .Items ) > 0 {
138- return OLSConfigList .Items [0 ], nil
139- }
140-
141- return uns.Unstructured {}, k8s_errors .NewNotFound (
142- schema.GroupResource {Group : "ols.openshifg.io" , Resource : "olsconfigs" },
143- "OLSConfig" )
144- }
145-
146- // BuildRAGConfigs builds the RAG configuration array.
147- // OpenStack RAG is always included first.
148- // OCP RAG is added if ocpVersion is provided.
149- func BuildRAGConfigs (instance * apiv1beta1.OpenStackLightspeed , ocpVersion string ) []interface {} {
150- rags := []interface {}{
151- // OpenStack RAG
152- map [string ]interface {}{
153- "image" : instance .Spec .RAGImage ,
154- "indexPath" : OpenStackLightspeedVectorDBPath ,
155- },
156- }
157-
158- // Add OCP RAG if enabled
159- if ocpVersion != "" {
160- rags = append (rags , map [string ]interface {}{
161- "image" : instance .Spec .RAGImage ,
162- "indexPath" : GetOCPVectorDBPath (ocpVersion ),
163- "indexID" : GetOCPIndexName (ocpVersion ),
164- })
165- }
166-
167- return rags
168- }
169-
170- // PatchOLSConfig patches OLSConfig with information from OpenStackLightspeed instance.
171- func PatchOLSConfig (
172- helper * common_helper.Helper ,
173- instance * apiv1beta1.OpenStackLightspeed ,
174- olsConfig * uns.Unstructured ,
175- ) error {
176- // Patch the Providers section
177- providersPatch := []interface {}{
178- map [string ]interface {}{
179- "credentialsSecretRef" : map [string ]interface {}{
180- "name" : instance .Spec .LLMCredentials ,
181- },
182- "models" : []interface {}{
183- map [string ]interface {}{
184- "name" : instance .Spec .ModelName ,
185- "parameters" : map [string ]interface {}{
186- "maxTokensForResponse" : float64 (instance .Spec .MaxTokensForResponse ), // unstructured JSON numbers default to float64
187- },
188- },
189- },
190- "name" : OpenStackLightspeedDefaultProvider ,
191- "type" : instance .Spec .LLMEndpointType ,
192- "url" : instance .Spec .LLMEndpoint ,
193- },
194- }
195-
196- provider := providersPatch [0 ].(map [string ]interface {})
197- if instance .Spec .LLMProjectID != "" {
198- if err := uns .SetNestedField (provider , instance .Spec .LLMProjectID , "projectID" ); err != nil {
199- return err
200- }
201- }
202-
203- if instance .Spec .LLMDeploymentName != "" {
204- if err := uns .SetNestedField (provider , instance .Spec .LLMDeploymentName , "deploymentName" ); err != nil {
205- return err
206- }
207- }
208-
209- if instance .Spec .LLMAPIVersion != "" {
210- if err := uns .SetNestedField (provider , instance .Spec .LLMAPIVersion , "apiVersion" ); err != nil {
211- return err
212- }
213- }
214-
215- if err := uns .SetNestedSlice (olsConfig .Object , providersPatch , "spec" , "llm" , "providers" ); err != nil {
216- return err
217- }
218-
219- // Patch the RAG section
220- // Build RAG array with priorities using BuildRAGConfigs
221- ragConfigs := BuildRAGConfigs (instance , instance .Status .ActiveOCPRAGVersion )
222-
223- if err := uns .SetNestedSlice (olsConfig .Object , ragConfigs , "spec" , "ols" , "rag" ); err != nil {
224- return err
225- }
226-
227- if instance .Spec .TLSCACertBundle != "" {
228- tlsCaCertBundle := instance .Spec .TLSCACertBundle
229- err := uns .SetNestedField (olsConfig .Object , tlsCaCertBundle , "spec" , "ols" , "additionalCAConfigMapRef" , "name" )
230- if err != nil {
231- return err
232- }
233- }
234-
235- modelName := instance .Spec .ModelName
236- err := uns .SetNestedField (olsConfig .Object , modelName , "spec" , "ols" , "defaultModel" )
237- if err != nil {
238- return err
239- }
240-
241- err = uns .SetNestedField (olsConfig .Object , OpenStackLightspeedDefaultProvider , "spec" , "ols" , "defaultProvider" )
242- if err != nil {
243- return err
244- }
245-
246- // Disable the OCP RAG
247- // TODO(lucasagomes): Remove this once we have a "query router" that can
248- // handle multiple RAGs nicely
249- err = uns .SetNestedField (olsConfig .Object , true , "spec" , "ols" , "byokRAGOnly" )
250- if err != nil {
251- return err
252- }
253-
254- // Disable or enable feedback collection
255- err = uns .SetNestedField (olsConfig .Object , instance .Spec .FeedbackDisabled , "spec" , "ols" , "userDataCollection" , "feedbackDisabled" )
256- if err != nil {
257- return err
258- }
259-
260- // Disable or enable transcripts collection
261- err = uns .SetNestedField (olsConfig .Object , instance .Spec .TranscriptsDisabled , "spec" , "ols" , "userDataCollection" , "transcriptsDisabled" )
262- if err != nil {
263- return err
264- }
265-
266- err = uns .SetNestedField (olsConfig .Object , GetSystemPrompt (), "spec" , "ols" , "querySystemPrompt" )
267- if err != nil {
268- return err
269- }
270-
271- // Add info which OpenStackLightspeed instance owns the OLSConfig
272- labels := olsConfig .GetLabels ()
273- updatedLabels := map [string ]interface {}{
274- OpenStackLightspeedOwnerIDLabel : string (instance .GetUID ()),
275- }
276- for k , v := range labels {
277- updatedLabels [k ] = v
278- }
279-
280- err = uns .SetNestedField (olsConfig .Object , updatedLabels , "metadata" , "labels" )
281- if err != nil {
282- return err
283- }
284-
285- // Add OpenStack finalizers
286- if ! controllerutil .AddFinalizer (olsConfig , helper .GetFinalizer ()) && instance .Status .Conditions == nil {
287- return fmt .Errorf ("cannot add finalizer" )
288- }
289-
290- return nil
291- }
292-
293- // IsOLSConfigReady returns true if OLSConfig's overallStatus is Ready
294- func IsOLSConfigReady (ctx context.Context , helper * common_helper.Helper ) (bool , error ) {
295- olsConfig , err := GetOLSConfig (ctx , helper )
296- if err != nil {
297- return false , err
298- }
299-
300- overallStatus , found , err := uns .NestedString (olsConfig .Object , "status" , "overallStatus" )
301- if err != nil {
302- return false , err
303- }
304-
305- if ! found || overallStatus != "Ready" {
306- return false , OLSConfigPing (ctx , helper )
307- }
308-
309- return true , nil
310- }
311-
31256// IsOwnedBy returns true if 'object' is owned by 'owner' based on OwnerReference UID.
31357func IsOwnedBy (object metav1.Object , owner metav1.Object ) bool {
31458 for _ , ref := range object .GetOwnerReferences () {
@@ -335,30 +79,3 @@ func GetRawClient(helper *common_helper.Helper) (client.Client, error) {
33579
33680 return rawClient , nil
33781}
338-
339- // OLSConfigPing adds a random label to the OLSConfig to trigger a reconciliation
340- // by the OpenShift Lightspeed operator. This causes the operator to update the Status field.
341- // Note: This is a workaround for a current limitation—when the OLS operator is installed
342- // in the openstack-lightspeed namespace, it does not automatically update the OLSConfig
343- // status as expected.
344- func OLSConfigPing (ctx context.Context , helper * common_helper.Helper ) error {
345- const randomLabelKey = "openstack-lightspeed/ping"
346-
347- olsConfig , err := GetOLSConfig (ctx , helper )
348- if err != nil {
349- return err
350- }
351-
352- labels := olsConfig .GetLabels ()
353- if labels == nil {
354- labels = make (map [string ]string )
355- }
356-
357- labels [randomLabelKey ] = strconv .Itoa (rand .Int ())
358- olsConfig .SetLabels (labels )
359-
360- if err := helper .GetClient ().Update (ctx , & olsConfig ); err != nil {
361- return err
362- }
363- return nil
364- }
0 commit comments