@@ -21,7 +21,7 @@ import (
2121 "k8s.io/client-go/tools/cache"
2222)
2323
24- // WatchServiceOffers runs the ServiceOffer + litellm-secrets informers and
24+ // WatchServiceOffers runs the ServiceOffer + upstream-auth Secret informers and
2525// pushes rendered RouteRules to apply on every change. The optional
2626// onFirstApply callback is invoked exactly once after the post-cache-sync
2727// refresh succeeds; it is the signal that the route source has produced its
@@ -33,14 +33,20 @@ func WatchServiceOffers(ctx context.Context, cfg *rest.Config, apply func([]Rout
3333 }
3434
3535 offerFactory := dynamicinformer .NewFilteredDynamicSharedInformerFactory (client , 0 , metav1 .NamespaceAll , nil )
36- secretFactory := dynamicinformer .NewFilteredDynamicSharedInformerFactory (client , 0 , metav1 .NamespaceAll , func (options * metav1.ListOptions ) {
36+ litellmSecretFactory := dynamicinformer .NewFilteredDynamicSharedInformerFactory (client , 0 , metav1 .NamespaceAll , func (options * metav1.ListOptions ) {
3737 options .FieldSelector = fields .OneTermEqualSelector ("metadata.name" , "litellm-secrets" ).String ()
3838 })
39+ hermesSecretFactory := dynamicinformer .NewFilteredDynamicSharedInformerFactory (client , 0 , metav1 .NamespaceAll , func (options * metav1.ListOptions ) {
40+ options .FieldSelector = fields .OneTermEqualSelector ("metadata.name" , "hermes-api-server" ).String ()
41+ })
3942 offers := offerFactory .ForResource (monetizeapi .ServiceOfferGVR ).Informer ()
40- secrets := secretFactory .ForResource (monetizeapi .SecretGVR ).Informer ()
43+ litellmSecrets := litellmSecretFactory .ForResource (monetizeapi .SecretGVR ).Informer ()
44+ hermesSecrets := hermesSecretFactory .ForResource (monetizeapi .SecretGVR ).Informer ()
4145
4246 refresh := func () (ok bool ) {
43- routes , err := routesFromStore (offers .GetStore ().List (), secrets .GetStore ().List ())
47+ secretItems := append ([]any {}, litellmSecrets .GetStore ().List ()... )
48+ secretItems = append (secretItems , hermesSecrets .GetStore ().List ()... )
49+ routes , err := routesFromStore (offers .GetStore ().List (), secretItems )
4450 if err != nil {
4551 log .Printf ("x402-serviceoffer-source: render routes: %v" , err )
4652 return false
@@ -59,11 +65,13 @@ func WatchServiceOffers(ctx context.Context, cfg *rest.Config, apply func([]Rout
5965 DeleteFunc : func (any ) { refresh () },
6066 }
6167 offers .AddEventHandler (handler )
62- secrets .AddEventHandler (handler )
68+ litellmSecrets .AddEventHandler (handler )
69+ hermesSecrets .AddEventHandler (handler )
6370
6471 go offers .Run (ctx .Done ())
65- go secrets .Run (ctx .Done ())
66- if ! cache .WaitForCacheSync (ctx .Done (), offers .HasSynced , secrets .HasSynced ) {
72+ go litellmSecrets .Run (ctx .Done ())
73+ go hermesSecrets .Run (ctx .Done ())
74+ if ! cache .WaitForCacheSync (ctx .Done (), offers .HasSynced , litellmSecrets .HasSynced , hermesSecrets .HasSynced ) {
6775 return fmt .Errorf ("wait for serviceoffer informer sync" )
6876 }
6977
@@ -75,7 +83,7 @@ func WatchServiceOffers(ctx context.Context, cfg *rest.Config, apply func([]Rout
7583}
7684
7785func routesFromStore (offerItems , secretItems []any ) ([]RouteRule , error ) {
78- upstreamAuthByNamespace , err := upstreamAuthByNamespace (secretItems )
86+ litellmAuthByNamespace , hermesAuthByNamespace , err := upstreamAuthByNamespace (secretItems )
7987 if err != nil {
8088 return nil , err
8189 }
@@ -103,7 +111,11 @@ func routesFromStore(offerItems, secretItems []any) ([]RouteRule, error) {
103111 continue
104112 }
105113
106- rule , err := routeRuleFromOffer (& offer , upstreamAuthByNamespace [offer .EffectiveNamespace ()])
114+ upstreamAuth := litellmAuthByNamespace [offer .EffectiveNamespace ()]
115+ if offer .IsAgent () {
116+ upstreamAuth = hermesAuthByNamespace [offer .Spec .Agent .Ref .Namespace ]
117+ }
118+ rule , err := routeRuleFromOffer (& offer , upstreamAuth )
107119 if err != nil {
108120 return nil , err
109121 }
@@ -194,36 +206,54 @@ func effectivePrice(offer *monetizeapi.ServiceOffer) (price, priceModel, perMTok
194206 }
195207}
196208
197- func upstreamAuthByNamespace (items []any ) (map [string ]string , error ) {
198- result := make (map [string ]string )
209+ func upstreamAuthByNamespace (items []any ) (map [string ]string , map [string ]string , error ) {
210+ litellmAuth := make (map [string ]string )
211+ hermesAuth := make (map [string ]string )
199212 for _ , item := range items {
200213 obj , ok := item .(* unstructured.Unstructured )
201- if ! ok || obj .GetName () != "litellm-secrets" {
214+ if ! ok {
215+ continue
216+ }
217+ dataKey := ""
218+ switch obj .GetName () {
219+ case "litellm-secrets" :
220+ dataKey = "LITELLM_MASTER_KEY"
221+ case "hermes-api-server" :
222+ dataKey = "API_SERVER_KEY"
223+ default :
202224 continue
203225 }
204226
205- value , found , err := unstructured .NestedString (obj .Object , "data" , "LITELLM_MASTER_KEY" )
227+ value , found , err := unstructured .NestedString (obj .Object , "data" , dataKey )
206228 if err != nil {
207- return nil , err
229+ return nil , nil , err
208230 }
209231 if ! found || value == "" {
210232 continue
211233 }
212234
213235 decoded , err := base64 .StdEncoding .DecodeString (value )
214236 if err != nil {
215- return nil , err
237+ return nil , nil , err
216238 }
217239 token := strings .TrimSpace (string (decoded ))
218240 if token == "" {
219241 continue
220242 }
221- result [obj .GetNamespace ()] = "Bearer " + token
243+ switch obj .GetName () {
244+ case "litellm-secrets" :
245+ litellmAuth [obj .GetNamespace ()] = "Bearer " + token
246+ case "hermes-api-server" :
247+ hermesAuth [obj .GetNamespace ()] = "Bearer " + token
248+ }
222249 }
223- return result , nil
250+ return litellmAuth , hermesAuth , nil
224251}
225252
226253func effectiveUpstreamAuth (offer * monetizeapi.ServiceOffer , upstreamAuth string ) string {
254+ if offer .IsAgent () {
255+ return upstreamAuth
256+ }
227257 if ! strings .EqualFold (offer .Spec .Upstream .Service , "litellm" ) {
228258 return ""
229259 }
0 commit comments