33# Licensed under the MIT License. See License.txt in the project root for license information.
44# --------------------------------------------------------------------------------------------
55
6+ import base64
67import json
78import os
89import time
@@ -80,14 +81,13 @@ def __init__(self, namespace: str = AGENT_NAMESPACE, kubeconfig_path: Optional[s
8081
8182 self .kubeconfig_path = kubeconfig_path
8283
84+ # Initialize Kubernetes client
85+ self ._init_k8s_client ()
8386 # Use provided helm manager or create a new one with kubeconfig
8487 self .helm_manager = helm_manager or HelmManager (kubeconfig_path = self .kubeconfig_path )
8588
8689 self ._load_existing_helm_release_config ()
8790
88- # Initialize Kubernetes client
89- self ._init_k8s_client ()
90-
9191 def set_aks_context (self , resource_group_name : Optional [str ] = None ,
9292 cluster_name : Optional [str ] = None ,
9393 subscription_id : Optional [str ] = None ):
@@ -159,7 +159,11 @@ def _load_existing_helm_release_config(self):
159159 self .llm_config_manager .model_list = model_list
160160 if not model_list :
161161 logger .warning ("No modelList found in Helm values" )
162- logger .debug ("LLM configuration loaded from Helm values: %d models found" , len (model_list ))
162+ else :
163+ logger .debug ("LLM configuration loaded from Helm values: %d models found" , len (model_list ))
164+
165+ # Read API keys from Kubernetes secret and populate model_list
166+ self ._populate_api_keys_from_secret ()
163167
164168 # Load managed identity client ID if present
165169 mcp_addons = helm_values .get ("mcpAddons" , {})
@@ -183,6 +187,59 @@ def _load_existing_helm_release_config(self):
183187 logger .error ("Failed to load LLM config from Helm values: %s" , e )
184188 raise AzCLIError (f"Failed to load LLM config from Helm values: { e } " )
185189
190+ def _populate_api_keys_from_secret (self ):
191+ """
192+ Read API keys from Kubernetes secret and populate them into model_list.
193+
194+ The model_list from Helm values contains environment variable references like
195+ '{{ env.AZURE_GPT_4_API_KEY }}'. This method reads the actual API keys from
196+ the Kubernetes secret and replaces those references with actual values.
197+ """
198+ try :
199+ # Try to read the secret
200+ secret = self .core_v1 .read_namespaced_secret (
201+ name = self .llm_secret_name ,
202+ namespace = self .namespace
203+ )
204+
205+ if not secret .data :
206+ logger .warning ("Secret '%s' exists but has no data" , self .llm_secret_name )
207+ return
208+
209+ # Decode secret data (base64 encoded)
210+ secret_data = {}
211+ for key , value in secret .data .items ():
212+ decoded_value = base64 .b64decode (value ).decode ("utf-8" )
213+ secret_data [key ] = decoded_value
214+
215+ logger .debug ("Read %d API keys from secret '%s'" , len (secret_data ), self .llm_secret_name )
216+
217+ from azext_aks_agent .agent .llm_providers .base import LLMProvider
218+
219+ # Populate API keys into model_list
220+
221+ for model_name , model_config in self .llm_config_manager .model_list .items ():
222+ # Get the expected secret key for this model
223+ secret_key = LLMProvider .sanitize_k8s_secret_key (model_config )
224+
225+ # If the secret contains this key, populate it
226+ if secret_key in secret_data :
227+ model_config ["api_key" ] = secret_data [secret_key ]
228+ logger .debug ("Populated API key for model '%s' from secret key '%s'" ,
229+ model_name , secret_key )
230+ else :
231+ logger .warning ("API key is not found for model '%s', please update the model '%s' API key." ,
232+ model_name , model_name )
233+
234+ except ApiException as e :
235+ if e .status == 404 :
236+ logger .debug ("Secret '%s' not found in namespace '%s', skipping API key population" ,
237+ self .llm_secret_name , self .namespace )
238+ else :
239+ logger .warning ("Failed to read secret '%s': %s" , self .llm_secret_name , e )
240+ except Exception as e : # pylint: disable=broad-exception-caught
241+ logger .warning ("Unexpected error reading API keys from secret: %s" , e )
242+
186243 def get_agent_pods (self ) -> Tuple [bool , Union [List [str ], str ]]:
187244 """
188245 Get running AKS agent pods from the Kubernetes cluster.
@@ -738,7 +795,7 @@ def _create_helm_values(self):
738795 env_vars = self .llm_config_manager .get_env_vars (self .llm_secret_name )
739796
740797 helm_values = {
741- "modelList" : self .llm_config_manager .model_list ,
798+ "modelList" : self .llm_config_manager .secured_model_list () ,
742799 "additionalEnvVars" : env_vars ,
743800 "nodeSelector" : {"kubernetes.io/os" : "linux" },
744801 }
0 commit comments