|
|
@@ -23,6 +23,7 @@ import (
|
|
|
"encoding/hex"
|
|
|
"fmt"
|
|
|
"maps"
|
|
|
+ "sort"
|
|
|
|
|
|
"github.com/LocoStack/loco-operator/api/v1alpha1"
|
|
|
"github.com/LocoStack/loco-operator/pkg/templates/litellm"
|
|
|
@@ -56,10 +57,41 @@ func (r *LiteLLMReconciler) ReconcileComponent(ctx context.Context, tmpl *v1alph
|
|
|
if err := r.ReconcileKey(ctx, "litellm", litellm.LITELLM_AUTH_SECRET_KEY, generateKey); err != nil {
|
|
|
return nil, fmt.Errorf("Failed to reconcile LiteLLM master key: %w", err)
|
|
|
}
|
|
|
- configHash, err := r.reconcileConfigMap(ctx)
|
|
|
+ deps := make([]client.Object, 0)
|
|
|
+ emList := make([]*v1alpha1.ExternalModel, 0)
|
|
|
+ mmList := make([]*v1alpha1.ManagedModel, 0)
|
|
|
+ for _, dep := range r.component.Spec.Dependencies {
|
|
|
+ switch dep.Kind {
|
|
|
+ case "ExternalModel":
|
|
|
+ em := &v1alpha1.ExternalModel{}
|
|
|
+ if err := r.client.Get(ctx, client.ObjectKey{Name: dep.Name, Namespace: dep.Namespace}, em); err != nil {
|
|
|
+ return nil, fmt.Errorf("Failed to get ExternalModel %s/%s: %w", dep.Namespace, dep.Name, err)
|
|
|
+ }
|
|
|
+ emList = append(emList, em)
|
|
|
+ deps = append(deps, em)
|
|
|
+ case "ManagedModel":
|
|
|
+ mm := &v1alpha1.ManagedModel{}
|
|
|
+ if err := r.client.Get(ctx, client.ObjectKey{Name: dep.Name, Namespace: dep.Namespace}, mm); err != nil {
|
|
|
+ return nil, fmt.Errorf("Failed to get ManagedModel %s/%s: %w", dep.Namespace, dep.Name, err)
|
|
|
+ }
|
|
|
+ mmList = append(mmList, mm)
|
|
|
+ deps = append(deps, mm)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ configHash, err := r.reconcileConfigMap(ctx, emList, mmList)
|
|
|
if err != nil {
|
|
|
return nil, fmt.Errorf("Failed to reconcile LiteLLM config: %w", err)
|
|
|
}
|
|
|
+ authSpecs := make(map[string]map[string]*v1alpha1.AuthSpec)
|
|
|
+ for _, em := range emList {
|
|
|
+ if em.Spec.Auth != nil {
|
|
|
+ if _, ok := authSpecs["ExternalModel"]; !ok {
|
|
|
+ authSpecs["ExternalModel"] = make(map[string]*v1alpha1.AuthSpec)
|
|
|
+ }
|
|
|
+ authSpecs["ExternalModel"][em.Name] = em.Spec.Auth
|
|
|
+ }
|
|
|
+ }
|
|
|
+ injectSecrets(tmpl, authSpecs)
|
|
|
if tmpl.Metadata.Annotations == nil {
|
|
|
tmpl.Metadata.Annotations = make(map[string]string)
|
|
|
}
|
|
|
@@ -69,10 +101,10 @@ func (r *LiteLLMReconciler) ReconcileComponent(ctx context.Context, tmpl *v1alph
|
|
|
if _, err := r.DefaultComponentReconciler.ReconcileComponent(ctx, tmpl, variables); err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
- return nil, nil
|
|
|
+ return deps, nil
|
|
|
}
|
|
|
|
|
|
-func (r *LiteLLMReconciler) reconcileConfigMap(ctx context.Context) (string, error) {
|
|
|
+func (r *LiteLLMReconciler) reconcileConfigMap(ctx context.Context, emList []*v1alpha1.ExternalModel, mmList []*v1alpha1.ManagedModel) (string, error) {
|
|
|
var o11yComp *v1alpha1.Component
|
|
|
if r.stack.Spec.Observability != nil && r.stack.Spec.Observability.Enabled {
|
|
|
o11yComp = &v1alpha1.Component{}
|
|
|
@@ -84,6 +116,8 @@ func (r *LiteLLMReconciler) reconcileConfigMap(ctx context.Context) (string, err
|
|
|
MasterKeyEnvName: litellm.LITELLM_MASTER_KEY_ENV_NAME,
|
|
|
Stack: r.stack,
|
|
|
ObservabilityComponent: o11yComp,
|
|
|
+ ExternalModels: emList,
|
|
|
+ ManagedModels: mmList,
|
|
|
}
|
|
|
config, err := configBuilder.BuildLiteLLMConfig()
|
|
|
if err != nil {
|
|
|
@@ -121,3 +155,59 @@ func generateKey() (string, error) {
|
|
|
}
|
|
|
return "sk-" + hex.EncodeToString(b), nil
|
|
|
}
|
|
|
+
|
|
|
+func injectSecrets(tmpl *v1alpha1.Template, authSpecs map[string]map[string]*v1alpha1.AuthSpec) {
|
|
|
+ envVars := []corev1.EnvVar{}
|
|
|
+ kinds := make([]string, 0, len(authSpecs))
|
|
|
+ for kind := range authSpecs {
|
|
|
+ kinds = append(kinds, kind)
|
|
|
+ }
|
|
|
+ sort.Strings(kinds)
|
|
|
+ for _, kind := range kinds {
|
|
|
+ kindAuthSpecs := authSpecs[kind]
|
|
|
+ names := make([]string, 0, len(kindAuthSpecs))
|
|
|
+ for name := range kindAuthSpecs {
|
|
|
+ names = append(names, name)
|
|
|
+ }
|
|
|
+ sort.Strings(names)
|
|
|
+ for _, name := range names {
|
|
|
+ auth := kindAuthSpecs[name]
|
|
|
+ var refName string
|
|
|
+ var refKey string
|
|
|
+ if auth.APIKey != nil {
|
|
|
+ refName = auth.APIKey.SecretRef.Name
|
|
|
+ refKey = auth.APIKey.SecretRef.Key
|
|
|
+ } else if auth.BearerToken != nil {
|
|
|
+ refName = auth.BearerToken.Name
|
|
|
+ refKey = auth.BearerToken.Key
|
|
|
+ }
|
|
|
+ if refName != "" && refKey != "" {
|
|
|
+ envVars = append(envVars, corev1.EnvVar{
|
|
|
+ Name: litellm.AuthEnvVarName(kind, name),
|
|
|
+ ValueFrom: &corev1.EnvVarSource{
|
|
|
+ SecretKeyRef: &corev1.SecretKeySelector{
|
|
|
+ LocalObjectReference: corev1.LocalObjectReference{Name: refName},
|
|
|
+ Key: refKey,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ })
|
|
|
+ }
|
|
|
+ if auth.Headers != nil {
|
|
|
+ for _, header := range auth.Headers {
|
|
|
+ if header.ValueFrom.SecretKeyRef != nil {
|
|
|
+ envVars = append(envVars, corev1.EnvVar{
|
|
|
+ Name: litellm.AuthEnvVarName(kind, name+"_"+header.Name),
|
|
|
+ ValueFrom: &corev1.EnvVarSource{
|
|
|
+ SecretKeyRef: &corev1.SecretKeySelector{
|
|
|
+ LocalObjectReference: header.ValueFrom.SecretKeyRef.LocalObjectReference,
|
|
|
+ Key: header.ValueFrom.SecretKeyRef.Key,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ tmpl.Spec.Runtime.Env = append(tmpl.Spec.Runtime.Env, envVars...)
|
|
|
+}
|