Skip to content

Commit c5aca66

Browse files
liulei.88innsd
authored andcommitted
feat(配置): 添加全局配置默认值支持
扩展全局配置功能,支持为多个模块设置默认值: 1. 添加defaults配置节,支持launch_type、preflight_mode等默认值设置 2. 在部署、生命周期等执行器中支持preflight_mode全局配置 3. 在CR相关操作中支持cr_public_endpoint_check全局配置 4. 在IAM角色创建中支持自定义策略列表和类型 5. 优化区域配置继承逻辑,优先使用全局volcengine.region (cherry picked from commit 6d29a07a3acf309e9bfb72d8bfd8066b56d60b94)
1 parent 1dbff4b commit c5aca66

File tree

9 files changed

+204
-35
lines changed

9 files changed

+204
-35
lines changed

agentkit/toolkit/builders/ve_pipeline.py

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -734,13 +734,22 @@ def config_updater(service: str, cr_config_dict: Dict[str, Any]) -> None:
734734
if not cr_result.success:
735735
raise Exception(cr_result.error)
736736

737-
# Ensure public endpoint access for image pulls
738-
self.reporter.info("Ensuring CR public endpoint access...")
739-
public_result = cr_service.ensure_public_endpoint(cr_config)
740-
741-
if not public_result.success:
742-
error_msg = f"Public endpoint configuration failed: {public_result.error}"
743-
raise Exception(error_msg)
737+
# Ensure public endpoint access for image pulls (controlled by global config)
738+
try:
739+
from agentkit.toolkit.config.global_config import get_global_config
740+
gc = get_global_config()
741+
do_check = getattr(getattr(gc, 'defaults', None), 'cr_public_endpoint_check', None)
742+
except Exception:
743+
do_check = None
744+
if do_check is False:
745+
self.reporter.info("Skipping CR public endpoint check per global config")
746+
else:
747+
self.reporter.info("Ensuring CR public endpoint access...")
748+
public_result = cr_service.ensure_public_endpoint(cr_config)
749+
750+
if not public_result.success:
751+
error_msg = f"Public endpoint configuration failed: {public_result.error}"
752+
raise Exception(error_msg)
744753

745754
self.reporter.success("CR resource preparation completed")
746755
self.reporter.info(f" Instance: {cr_result.instance_name}")
@@ -1131,4 +1140,4 @@ def download_and_show_logs(run_id: str):
11311140
return image_url
11321141

11331142
except Exception as e:
1134-
raise Exception(f"Build execution failed: {str(e)}")
1143+
raise Exception(f"Build execution failed: {str(e)}")

agentkit/toolkit/cli/cli_config.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,45 @@ def _set_global_field(field_value: str):
438438
config.iam_host = value
439439
elif field == 'schema':
440440
config.iam_schema = value
441+
elif section == 'defaults':
442+
if field == 'launch_type':
443+
clean_value = value.strip() if value is not None else None
444+
if clean_value == "":
445+
clean_value = None
446+
config.defaults.launch_type = clean_value
447+
elif field == 'preflight_mode':
448+
clean_value = value.strip().lower() if value is not None else None
449+
if clean_value == "":
450+
clean_value = None
451+
# Accept only known modes
452+
allowed = {"prompt", "fail", "warn", "skip"}
453+
if clean_value and clean_value not in allowed:
454+
raise AttributeError(f"Invalid preflight_mode: {value}. Allowed: prompt|fail|warn|skip")
455+
config.defaults.preflight_mode = clean_value
456+
elif field == 'cr_public_endpoint_check':
457+
clean_value = value.strip().lower() if value is not None else None
458+
if clean_value == "":
459+
clean_value = None
460+
if clean_value is None:
461+
config.defaults.cr_public_endpoint_check = None
462+
else:
463+
truthy = {"true", "1", "yes", "y"}
464+
falsy = {"false", "0", "no", "n"}
465+
if clean_value in truthy:
466+
config.defaults.cr_public_endpoint_check = True
467+
elif clean_value in falsy:
468+
config.defaults.cr_public_endpoint_check = False
469+
else:
470+
raise AttributeError(f"Invalid cr_public_endpoint_check: {value}. Allowed: true|false|1|0|yes|no")
471+
elif field == 'iam_role_policies':
472+
clean_value = value.strip() if value is not None else None
473+
if clean_value == "" or clean_value is None:
474+
config.defaults.iam_role_policies = None
475+
else:
476+
policies = [p.strip() for p in clean_value.split(',') if p.strip()]
477+
config.defaults.iam_role_policies = policies
478+
else:
479+
raise AttributeError(f"defaults has no field: {field}")
441480
else:
442481
console.print(f"[red]❌ Unknown config section: {section}[/red]")
443482
console.print("\nSupported sections: volcengine, cr, tos")

agentkit/toolkit/cli/cli_status.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,15 +122,15 @@ def status_command(
122122
if result.endpoint_url:
123123
table.add_row("🌐 Endpoint", result.endpoint_url)
124124
if result.service_id:
125-
table.add_row("☁️ Service ID", result.service_id)
125+
table.add_row("☁️ Service ID", result.service_id)
126126
if result.uptime_seconds:
127127
# Format uptime to human-readable format
128128
uptime = result.uptime_seconds
129129
hours = uptime // 3600
130130
minutes = (uptime % 3600) // 60
131131
seconds = uptime % 60
132132
uptime_str = f"{hours}h {minutes}m {seconds}s" if hours > 0 else f"{minutes}m {seconds}s"
133-
table.add_row("⏱️ Uptime", uptime_str)
133+
table.add_row("⏱️ Uptime", uptime_str)
134134

135135
# Extract other information from metadata
136136
details = result.metadata or {}

agentkit/toolkit/config/global_config.py

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,38 @@ class GlobalConfig:
130130
iam_host: str = ""
131131
iam_schema: str = "https"
132132

133+
@dataclass
134+
class Defaults:
135+
launch_type: Optional[str] = None
136+
preflight_mode: Optional[str] = None
137+
cr_public_endpoint_check: Optional[bool] = None
138+
iam_role_policies: Optional[list] = None
139+
140+
def to_dict(self):
141+
data = {}
142+
if self.launch_type:
143+
data["launch_type"] = self.launch_type
144+
if self.preflight_mode:
145+
data["preflight_mode"] = self.preflight_mode
146+
if self.cr_public_endpoint_check is not None:
147+
data["cr_public_endpoint_check"] = self.cr_public_endpoint_check
148+
if self.iam_role_policies is not None:
149+
data["iam_role_policies"] = self.iam_role_policies
150+
return data
151+
152+
@classmethod
153+
def from_dict(cls, data: dict):
154+
return cls(
155+
launch_type=data.get("launch_type"),
156+
preflight_mode=data.get("preflight_mode"),
157+
cr_public_endpoint_check=data.get("cr_public_endpoint_check"),
158+
iam_role_policies=data.get("iam_role_policies"),
159+
)
160+
161+
defaults: 'GlobalConfig.Defaults' = field(default_factory=lambda: GlobalConfig.Defaults())
162+
133163
def to_dict(self):
134-
return {
164+
base = {
135165
"volcengine": self.volcengine.to_dict(),
136166
"cr": self.cr.to_dict(),
137167
"tos": self.tos.to_dict(),
@@ -144,6 +174,10 @@ def to_dict(self):
144174
"schema": self.iam_schema,
145175
},
146176
}
177+
defaults_dict = self.defaults.to_dict()
178+
if defaults_dict:
179+
base["defaults"] = defaults_dict
180+
return base
147181

148182
@classmethod
149183
def from_dict(cls, data: dict):
@@ -155,6 +189,7 @@ def from_dict(cls, data: dict):
155189
agentkit_schema=(data.get("agentkit", {}) or {}).get("schema", "https"),
156190
iam_host=(data.get("iam", {}) or {}).get("host", ""),
157191
iam_schema=(data.get("iam", {}) or {}).get("schema", "https"),
192+
defaults=GlobalConfig.Defaults.from_dict(data.get("defaults", {}) or {}),
158193
)
159194

160195

@@ -361,6 +396,16 @@ def apply_global_config_defaults(
361396
'tos_region': ('tos', 'region'),
362397
})
363398

399+
# Region fields (cloud/hybrid) inherit from global volcengine.region when project missing
400+
if isinstance(config_obj, (HybridStrategyConfig, CloudStrategyConfig)):
401+
field_mappings.update({
402+
'region': ('volcengine', 'region'),
403+
})
404+
if isinstance(config_obj, CloudStrategyConfig):
405+
field_mappings.update({
406+
'cr_region': ('volcengine', 'region'),
407+
})
408+
364409
# Apply global config values
365410
for field_name, (section, attr) in field_mappings.items():
366411
# Skip if the target field does not exist on the config object

agentkit/toolkit/executors/deploy_executor.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,21 @@ def execute(
8989
Exception: Any exception during deployment is caught and returned as failed result
9090
"""
9191
try:
92+
# Override preflight_mode from global config defaults if configured
93+
try:
94+
from agentkit.toolkit.config.global_config import get_global_config
95+
gc = get_global_config()
96+
gm = getattr(getattr(gc, 'defaults', None), 'preflight_mode', None)
97+
if gm:
98+
gm_map = {
99+
'prompt': PreflightMode.PROMPT,
100+
'fail': PreflightMode.FAIL,
101+
'warn': PreflightMode.WARN,
102+
'skip': PreflightMode.SKIP,
103+
}
104+
preflight_mode = gm_map.get(gm.lower(), preflight_mode)
105+
except Exception:
106+
pass
92107
self.logger.info("Loading configuration...")
93108
config = self._load_config(config_dict, config_file)
94109
self._validate_config(config)

agentkit/toolkit/executors/init_executor.py

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,13 @@ def _setup_config_launch_type(self, config_manager, common_config):
440440
# Create config directly to avoid auto-injection from global config
441441
cloud_config = CloudStrategyConfig()
442442

443+
# Region: prefer global volcengine.region if available
444+
global_region = None
445+
if global_config and getattr(global_config.volcengine, 'region', None):
446+
global_region = global_config.volcengine.region
447+
cloud_config.region = global_region or 'cn-beijing'
448+
cloud_config.cr_region = global_region or 'cn-beijing'
449+
443450
# Empty string means "inherit from global config at runtime"
444451
if global_config and global_config.cr.instance_name:
445452
cloud_config.cr_instance_name = ""
@@ -464,10 +471,11 @@ def _setup_config_launch_type(self, config_manager, common_config):
464471
else:
465472
cloud_config.tos_prefix = "agentkit-builds"
466473

467-
if global_config and global_config.tos.region:
468-
cloud_config.tos_region = ""
474+
# TOS region: prefer explicit value from global.tos.region; otherwise use global volcengine.region
475+
if global_config and getattr(global_config.tos, 'region', None):
476+
cloud_config.tos_region = global_config.tos.region
469477
else:
470-
cloud_config.tos_region = "cn-beijing"
478+
cloud_config.tos_region = cloud_config.region
471479

472480
# Project-specific values (always set, not inherited)
473481
cloud_config.cr_repo_name = common_config.agent_name
@@ -481,6 +489,11 @@ def _setup_config_launch_type(self, config_manager, common_config):
481489
# Create config directly to avoid auto-injection from global config
482490
# Hybrid mode only needs CR config (no TOS needed)
483491
hybrid_config = HybridStrategyConfig()
492+
# Region: prefer global volcengine.region
493+
global_region = None
494+
if global_config and getattr(global_config.volcengine, 'region', None):
495+
global_region = global_config.volcengine.region
496+
hybrid_config.region = global_region or 'cn-beijing'
484497

485498
if global_config and global_config.cr.instance_name:
486499
hybrid_config.cr_instance_name = ""
@@ -519,7 +532,13 @@ def _create_config_file(
519532
config_manager = get_config(config_path=config_file_path)
520533
common_config = config_manager.get_common_config()
521534

522-
common_config.launch_type = 'cloud'
535+
try:
536+
global_cfg = get_global_config()
537+
default_lt = getattr(getattr(global_cfg, 'defaults', None), 'launch_type', None)
538+
except Exception:
539+
default_lt = None
540+
541+
common_config.launch_type = default_lt or 'cloud'
523542
common_config.language = language
524543
common_config.language_version = language_version
525544
common_config.agent_name = project_name

agentkit/toolkit/executors/lifecycle_executor.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,22 @@ def launch(
135135

136136
# Preflight check: verify required cloud services for both build and deploy
137137
# We do this once at the start for better UX (single prompt for all missing services)
138+
# Override preflight_mode from global config defaults if configured
139+
try:
140+
from agentkit.toolkit.config.global_config import get_global_config
141+
gc = get_global_config()
142+
gm = getattr(getattr(gc, 'defaults', None), 'preflight_mode', None)
143+
if gm:
144+
gm_map = {
145+
'prompt': PreflightMode.PROMPT,
146+
'fail': PreflightMode.FAIL,
147+
'warn': PreflightMode.WARN,
148+
'skip': PreflightMode.SKIP,
149+
}
150+
preflight_mode = gm_map.get(gm.lower(), preflight_mode)
151+
except Exception:
152+
pass
153+
138154
if preflight_mode != PreflightMode.SKIP:
139155
# Load config first to get launch_type
140156
config = self._load_config(config_dict, config_file)

agentkit/toolkit/strategies/hybrid_strategy.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -304,10 +304,19 @@ def _handle_cr_push(self, common_config: CommonConfig, result: BuildResult, stra
304304
if not ensure_result.success:
305305
raise Exception(ensure_result.error or "Failed to ensure CR resources")
306306

307-
# Ensure public endpoint is enabled for CR instance
308-
public_result = cr_service.ensure_public_endpoint(cr_cfg)
309-
if not public_result.success:
310-
raise Exception(public_result.error or "Failed to enable CR public endpoint")
307+
# Ensure public endpoint is enabled for CR instance (controlled by global config)
308+
try:
309+
from agentkit.toolkit.config.global_config import get_global_config
310+
gc = get_global_config()
311+
do_check = getattr(getattr(gc, 'defaults', None), 'cr_public_endpoint_check', None)
312+
except Exception:
313+
do_check = None
314+
if do_check is False:
315+
self.reporter.info("Skipping CR public endpoint check per global config")
316+
else:
317+
public_result = cr_service.ensure_public_endpoint(cr_cfg)
318+
if not public_result.success:
319+
raise Exception(public_result.error or "Failed to enable CR public endpoint")
311320

312321
# Write back any auto-created names to config
313322
if ensure_result.instance_name and ensure_result.instance_name != strategy_config.cr_instance_name:

agentkit/toolkit/volcengine/iam.py

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,13 @@ def create_role(self, role_name: str, trust_policy_document: str) -> Optional[Cr
252252
data="{}"
253253
)
254254
response_data = json.loads(res)
255-
return CreateRoleResponse(**response_data.get('Result', {}))
255+
result_data = response_data.get('Result', {})
256+
role_data = result_data.get('Role')
257+
if isinstance(role_data, dict):
258+
tpd = role_data.get('TrustPolicyDocument')
259+
if isinstance(tpd, dict):
260+
role_data['TrustPolicyDocument'] = json.dumps(tpd)
261+
return CreateRoleResponse(**result_data)
256262

257263

258264
def attach_role_policy(self, role_name: str, policy_name: str, policy_type: str) -> Optional[AttachRolePolicyResponse]:
@@ -293,20 +299,31 @@ def ensure_role_for_agentkit(self, role_name: str) -> bool:
293299
AgentKitTosAccess
294300
AgentKitToolAccess
295301
'''
296-
policies = [
297-
"ArkReadOnlyAccess",
298-
"TLSReadOnlyAccess",
299-
"APMPlusServerReadOnlyAccess",
300-
"VikingdbReadOnlyAccess",
301-
"ESCloudReadOnlyAccess",
302-
"LLMShieldProtectSdkAccess",
303-
"AgentKitReadOnlyAccess",
304-
"TorchlightApiFullAccess",
305-
"Mem0ReadOnlyAccess",
306-
"IDReadOnlyAccess",
307-
"AgentKitTosAccess",
308-
"AgentKitToolAccess",
309-
]
310-
for policy in policies:
302+
try:
303+
from agentkit.toolkit.config.global_config import get_global_config
304+
gc = get_global_config()
305+
defaults = getattr(gc, 'defaults', None)
306+
custom_policies = getattr(defaults, 'iam_role_policies', None) if defaults else None
307+
except Exception:
308+
custom_policies = None
309+
310+
if custom_policies and isinstance(custom_policies, list) and len(custom_policies) > 0:
311+
to_attach = custom_policies
312+
else:
313+
to_attach = [
314+
"ArkReadOnlyAccess",
315+
"TLSReadOnlyAccess",
316+
"APMPlusServerReadOnlyAccess",
317+
"VikingdbReadOnlyAccess",
318+
"ESCloudReadOnlyAccess",
319+
"LLMShieldProtectSdkAccess",
320+
"AgentKitReadOnlyAccess",
321+
"TorchlightApiFullAccess",
322+
"Mem0ReadOnlyAccess",
323+
"IDReadOnlyAccess",
324+
"AgentKitTosAccess",
325+
"AgentKitToolAccess",
326+
]
327+
for policy in to_attach:
311328
self.attach_role_policy(role_name, policy_name=policy, policy_type="System")
312329
return True

0 commit comments

Comments
 (0)