88from pydantic import BaseModel , Field
99from rich .console import Console
1010
11- from agentex .lib .cli .utils .auth_utils import _encode_principal_context
1211from agentex .lib .cli .utils .exceptions import DeploymentError , HelmError
12+ from agentex .lib .sdk .config .environment_config import AgentEnvironmentConfig
1313from agentex .lib .cli .utils .kubectl_utils import check_and_switch_cluster_context
1414from agentex .lib .cli .utils .path_utils import calculate_docker_acp_module , PathResolutionError
1515from agentex .lib .environment_variables import EnvVarKeys
1616from agentex .lib .sdk .config .agent_config import AgentConfig
1717from agentex .lib .sdk .config .agent_manifest import AgentManifest
18- from agentex . lib . sdk . config . deployment_config import ClusterConfig
18+
1919from agentex .lib .utils .logging import make_logger
2020
2121logger = make_logger (__name__ )
@@ -76,25 +76,6 @@ def add_helm_repo() -> None:
7676 raise HelmError (f"Failed to add helm repository: { e } " ) from e
7777
7878
79- def load_override_config (override_file_path : str | None = None ) -> ClusterConfig | None :
80- """Load override configuration from specified file path"""
81- if not override_file_path :
82- return None
83-
84- override_path = Path (override_file_path )
85- if not override_path .exists ():
86- raise DeploymentError (f"Override file not found: { override_file_path } " )
87-
88- try :
89- with open (override_path ) as f :
90- config_data = yaml .safe_load (f )
91- return ClusterConfig (** config_data ) if config_data else None
92- except Exception as e :
93- raise DeploymentError (
94- f"Failed to load override config from { override_file_path } : { e } "
95- ) from e
96-
97-
9879
9980def convert_env_vars_dict_to_list (env_vars : dict [str , str ]) -> list [dict [str , str ]]:
10081 """Convert a dictionary of environment variables to a list of dictionaries"""
@@ -116,13 +97,13 @@ def add_acp_command_to_helm_values(helm_values: dict[str, Any], manifest: AgentM
11697
11798def merge_deployment_configs (
11899 manifest : AgentManifest ,
119- cluster_config : ClusterConfig | None ,
100+ agent_env_config : AgentEnvironmentConfig | None ,
120101 deploy_overrides : InputDeployOverrides ,
121102 manifest_path : str ,
122103) -> dict [str , Any ]:
123104 agent_config : AgentConfig = manifest .agent
124105
125- """Merge global deployment config with cluster -specific overrides into helm values"""
106+ """Merge global deployment config with environment -specific overrides into helm values"""
126107 if not manifest .deployment :
127108 raise DeploymentError ("No deployment configuration found in manifest" )
128109
@@ -185,18 +166,27 @@ def merge_deployment_configs(
185166 "taskQueue" : temporal_config .queue_name ,
186167 }
187168
188- # Collect all environment variables with conflict detection
169+ # Collect all environment variables with proper precedence
170+ # Priority: manifest -> environments.yaml -> secrets (highest)
189171 all_env_vars : dict [str , str ] = {}
190172 secret_env_vars : list [dict [str , str ]] = []
191173
192- # Start with agent_config env vars
174+ # Start with agent_config env vars from manifest
193175 if agent_config .env :
194176 all_env_vars .update (agent_config .env )
177+
178+ # Override with environment config env vars if they exist
179+ if agent_env_config and agent_env_config .helm_overrides and "env" in agent_env_config .helm_overrides :
180+ env_overrides = agent_env_config .helm_overrides ["env" ]
181+ if isinstance (env_overrides , list ):
182+ # Convert list format to dict for easier merging
183+ env_override_dict : dict [str , str ] = {}
184+ for env_var in env_overrides :
185+ if isinstance (env_var , dict ) and "name" in env_var and "value" in env_var :
186+ env_override_dict [str (env_var ["name" ])] = str (env_var ["value" ])
187+ all_env_vars .update (env_override_dict )
188+
195189
196- # Add auth principal env var if manifest principal is set
197- encoded_principal = _encode_principal_context (manifest )
198- if encoded_principal :
199- all_env_vars [EnvVarKeys .AUTH_PRINCIPAL_B64 .value ] = encoded_principal
200190
201191 # Handle credentials and check for conflicts
202192 if agent_config .credentials :
@@ -228,57 +218,23 @@ def merge_deployment_configs(
228218 }
229219 )
230220
231- # Apply cluster-specific overrides
232- if cluster_config :
233- if cluster_config .image :
234- if cluster_config .image .repository :
235- helm_values ["global" ]["image" ]["repository" ] = (
236- cluster_config .image .repository
237- )
238- if cluster_config .image .tag :
239- helm_values ["global" ]["image" ]["tag" ] = cluster_config .image .tag
240-
241- if cluster_config .replicaCount is not None :
242- helm_values ["replicaCount" ] = cluster_config .replicaCount
243-
244- if cluster_config .resources :
245- if cluster_config .resources .requests :
246- helm_values ["resources" ]["requests" ].update (
247- {
248- "cpu" : cluster_config .resources .requests .cpu ,
249- "memory" : cluster_config .resources .requests .memory ,
250- }
251- )
252- if cluster_config .resources .limits :
253- helm_values ["resources" ]["limits" ].update (
254- {
255- "cpu" : cluster_config .resources .limits .cpu ,
256- "memory" : cluster_config .resources .limits .memory ,
257- }
258- )
259-
260- # Handle cluster env vars with conflict detection
261- if cluster_config .env :
262- # Convert cluster env list to dict for easier conflict detection
263- cluster_env_dict = {env_var ["name" ]: env_var ["value" ] for env_var in cluster_config .env }
264-
265- # Check for conflicts with secret env vars
266- for secret_env_var in secret_env_vars :
267- if secret_env_var ["name" ] in cluster_env_dict :
268- logger .warning (
269- f"Environment variable '{ secret_env_var ['name' ]} ' is defined in both "
270- f"cluster config env and secretEnvVars. The secret value will take precedence."
271- )
272- del cluster_env_dict [secret_env_var ["name" ]]
273-
274- # Update all_env_vars with cluster overrides
275- all_env_vars .update (cluster_env_dict )
276-
277- # Apply additional arbitrary overrides
278- if cluster_config .additional_overrides :
279- _deep_merge (helm_values , cluster_config .additional_overrides )
221+ # Apply agent environment configuration overrides
222+ if agent_env_config :
223+ # Add auth principal env var if environment config is set
224+ if agent_env_config .auth :
225+ from agentex .lib .cli .utils .auth_utils import _encode_principal_context_from_env_config
226+ encoded_principal = _encode_principal_context_from_env_config (agent_env_config .auth )
227+ logger .info (f"Encoding auth principal from { agent_env_config .auth } " )
228+ if encoded_principal :
229+ all_env_vars [EnvVarKeys .AUTH_PRINCIPAL_B64 .value ] = encoded_principal
230+ else :
231+ raise DeploymentError (f"Auth principal unable to be encoded for agent_env_config: { agent_env_config } " )
232+
233+ if agent_env_config .helm_overrides :
234+ _deep_merge (helm_values , agent_env_config .helm_overrides )
280235
281236 # Set final environment variables
237+ # Environment variable precedence: manifest -> environments.yaml -> secrets (highest)
282238 if all_env_vars :
283239 helm_values ["env" ] = convert_env_vars_dict_to_list (all_env_vars )
284240
@@ -295,7 +251,7 @@ def merge_deployment_configs(
295251 # Handle image pull secrets
296252 if manifest .deployment and manifest .deployment .imagePullSecrets :
297253 pull_secrets = [
298- pull_secret .to_dict ()
254+ pull_secret .model_dump ()
299255 for pull_secret in manifest .deployment .imagePullSecrets
300256 ]
301257 helm_values ["global" ]["imagePullSecrets" ] = pull_secrets
@@ -333,7 +289,7 @@ def deploy_agent(
333289 cluster_name : str ,
334290 namespace : str ,
335291 deploy_overrides : InputDeployOverrides ,
336- override_file_path : str | None = None ,
292+ environment_name : str | None = None ,
337293) -> None :
338294 """Deploy an agent using helm"""
339295
@@ -345,21 +301,23 @@ def deploy_agent(
345301 check_and_switch_cluster_context (cluster_name )
346302
347303 manifest = AgentManifest .from_yaml (file_path = manifest_path )
348- override_config = load_override_config (override_file_path )
349304
350- # Provide feedback about override configuration
351- if override_config :
352- console .print (f"[green]✓[/green] Using override config: { override_file_path } " )
353- else :
354- console .print (
355- "[yellow]ℹ[/yellow] No override config specified, using global defaults"
356- )
305+ # Load agent environment configuration
306+ agent_env_config = None
307+ if environment_name :
308+ manifest_dir = Path (manifest_path ).parent
309+ environments_config = manifest .load_environments_config (manifest_dir )
310+ if environments_config :
311+ agent_env_config = environments_config .get_config_for_env (environment_name )
312+ console .print (f"[green]✓[/green] Using environment config: { environment_name } " )
313+ else :
314+ console .print (f"[yellow]⚠[/yellow] No environments.yaml found, skipping environment-specific config" )
357315
358316 # Add helm repository/update
359317 add_helm_repo ()
360318
361319 # Merge configurations
362- helm_values = merge_deployment_configs (manifest , override_config , deploy_overrides , manifest_path )
320+ helm_values = merge_deployment_configs (manifest , agent_env_config , deploy_overrides , manifest_path )
363321
364322 # Create values file
365323 values_file = create_helm_values_file (helm_values )
0 commit comments