bedrock-agentcore-starter-toolkit 0.0.1__py3-none-any.whl → 0.1.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of bedrock-agentcore-starter-toolkit might be problematic. Click here for more details.
- bedrock_agentcore_starter_toolkit/__init__.py +5 -0
- bedrock_agentcore_starter_toolkit/cli/cli.py +32 -0
- bedrock_agentcore_starter_toolkit/cli/common.py +44 -0
- bedrock_agentcore_starter_toolkit/cli/gateway/__init__.py +1 -0
- bedrock_agentcore_starter_toolkit/cli/gateway/commands.py +88 -0
- bedrock_agentcore_starter_toolkit/cli/runtime/__init__.py +1 -0
- bedrock_agentcore_starter_toolkit/cli/runtime/commands.py +651 -0
- bedrock_agentcore_starter_toolkit/cli/runtime/configuration_manager.py +133 -0
- bedrock_agentcore_starter_toolkit/notebook/__init__.py +5 -0
- bedrock_agentcore_starter_toolkit/notebook/runtime/__init__.py +1 -0
- bedrock_agentcore_starter_toolkit/notebook/runtime/bedrock_agentcore.py +239 -0
- bedrock_agentcore_starter_toolkit/operations/__init__.py +1 -0
- bedrock_agentcore_starter_toolkit/operations/gateway/README.md +277 -0
- bedrock_agentcore_starter_toolkit/operations/gateway/__init__.py +6 -0
- bedrock_agentcore_starter_toolkit/operations/gateway/client.py +456 -0
- bedrock_agentcore_starter_toolkit/operations/gateway/constants.py +152 -0
- bedrock_agentcore_starter_toolkit/operations/gateway/create_lambda.py +85 -0
- bedrock_agentcore_starter_toolkit/operations/gateway/create_role.py +90 -0
- bedrock_agentcore_starter_toolkit/operations/gateway/exceptions.py +13 -0
- bedrock_agentcore_starter_toolkit/operations/runtime/__init__.py +26 -0
- bedrock_agentcore_starter_toolkit/operations/runtime/configure.py +241 -0
- bedrock_agentcore_starter_toolkit/operations/runtime/create_role.py +404 -0
- bedrock_agentcore_starter_toolkit/operations/runtime/invoke.py +129 -0
- bedrock_agentcore_starter_toolkit/operations/runtime/launch.py +439 -0
- bedrock_agentcore_starter_toolkit/operations/runtime/models.py +79 -0
- bedrock_agentcore_starter_toolkit/operations/runtime/status.py +66 -0
- bedrock_agentcore_starter_toolkit/services/codebuild.py +332 -0
- bedrock_agentcore_starter_toolkit/services/ecr.py +84 -0
- bedrock_agentcore_starter_toolkit/services/runtime.py +473 -0
- bedrock_agentcore_starter_toolkit/utils/endpoints.py +32 -0
- bedrock_agentcore_starter_toolkit/utils/logging_config.py +72 -0
- bedrock_agentcore_starter_toolkit/utils/runtime/config.py +129 -0
- bedrock_agentcore_starter_toolkit/utils/runtime/container.py +310 -0
- bedrock_agentcore_starter_toolkit/utils/runtime/entrypoint.py +197 -0
- bedrock_agentcore_starter_toolkit/utils/runtime/logs.py +33 -0
- bedrock_agentcore_starter_toolkit/utils/runtime/policy_template.py +74 -0
- bedrock_agentcore_starter_toolkit/utils/runtime/schema.py +151 -0
- bedrock_agentcore_starter_toolkit/utils/runtime/templates/Dockerfile.j2 +44 -0
- bedrock_agentcore_starter_toolkit/utils/runtime/templates/dockerignore.template +68 -0
- bedrock_agentcore_starter_toolkit/utils/runtime/templates/execution_role_policy.json.j2 +98 -0
- bedrock_agentcore_starter_toolkit/utils/runtime/templates/execution_role_trust_policy.json.j2 +21 -0
- bedrock_agentcore_starter_toolkit-0.1.1.dist-info/METADATA +137 -0
- bedrock_agentcore_starter_toolkit-0.1.1.dist-info/RECORD +47 -0
- bedrock_agentcore_starter_toolkit-0.1.1.dist-info/entry_points.txt +2 -0
- bedrock_agentcore_starter_toolkit-0.1.1.dist-info/licenses/NOTICE.txt +190 -0
- bedrock_agentcore_starter_toolkit/init.py +0 -3
- bedrock_agentcore_starter_toolkit-0.0.1.dist-info/METADATA +0 -26
- bedrock_agentcore_starter_toolkit-0.0.1.dist-info/RECORD +0 -5
- {bedrock_agentcore_starter_toolkit-0.0.1.dist-info → bedrock_agentcore_starter_toolkit-0.1.1.dist-info}/WHEEL +0 -0
- /bedrock_agentcore_starter_toolkit-0.0.1.dist-info/licenses/LICENSE → /bedrock_agentcore_starter_toolkit-0.1.1.dist-info/licenses/LICENSE.txt +0 -0
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
"""Launch operation - deploys Bedrock AgentCore locally or to cloud."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import logging
|
|
5
|
+
import time
|
|
6
|
+
import urllib.parse
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import Optional
|
|
9
|
+
|
|
10
|
+
import boto3
|
|
11
|
+
from botocore.exceptions import ClientError
|
|
12
|
+
|
|
13
|
+
from ...services.codebuild import CodeBuildService
|
|
14
|
+
from ...services.ecr import deploy_to_ecr, get_or_create_ecr_repository
|
|
15
|
+
from ...services.runtime import BedrockAgentCoreClient
|
|
16
|
+
from ...utils.runtime.config import load_config, save_config
|
|
17
|
+
from ...utils.runtime.container import ContainerRuntime
|
|
18
|
+
from .create_role import get_or_create_runtime_execution_role
|
|
19
|
+
from .models import LaunchResult
|
|
20
|
+
|
|
21
|
+
log = logging.getLogger(__name__)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _ensure_ecr_repository(agent_config, project_config, config_path, agent_name, region):
|
|
25
|
+
"""Ensure ECR repository exists (idempotent)."""
|
|
26
|
+
ecr_uri = agent_config.aws.ecr_repository
|
|
27
|
+
|
|
28
|
+
# Step 1: Check if we already have a repository in config
|
|
29
|
+
if ecr_uri:
|
|
30
|
+
log.info("Using ECR repository from config: %s", ecr_uri)
|
|
31
|
+
return ecr_uri
|
|
32
|
+
|
|
33
|
+
# Step 2: Create repository if needed (idempotent)
|
|
34
|
+
if agent_config.aws.ecr_auto_create:
|
|
35
|
+
log.info("Getting or creating ECR repository for agent: %s", agent_name)
|
|
36
|
+
|
|
37
|
+
ecr_uri = get_or_create_ecr_repository(agent_name, region)
|
|
38
|
+
|
|
39
|
+
# Update the config
|
|
40
|
+
agent_config.aws.ecr_repository = ecr_uri
|
|
41
|
+
agent_config.aws.ecr_auto_create = False
|
|
42
|
+
|
|
43
|
+
# Update the project config and save
|
|
44
|
+
project_config.agents[agent_config.name] = agent_config
|
|
45
|
+
save_config(project_config, config_path)
|
|
46
|
+
|
|
47
|
+
log.info("✅ ECR repository available: %s", ecr_uri)
|
|
48
|
+
return ecr_uri
|
|
49
|
+
|
|
50
|
+
# Step 3: No repository and auto-create disabled
|
|
51
|
+
raise ValueError("ECR repository not configured and auto-create not enabled")
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _validate_execution_role(role_arn: str, session: boto3.Session) -> bool:
|
|
55
|
+
"""Validate that execution role exists and has correct trust policy for Bedrock AgentCore."""
|
|
56
|
+
iam = session.client("iam")
|
|
57
|
+
role_name = role_arn.split("/")[-1]
|
|
58
|
+
|
|
59
|
+
try:
|
|
60
|
+
response = iam.get_role(RoleName=role_name)
|
|
61
|
+
trust_policy = response["Role"]["AssumeRolePolicyDocument"]
|
|
62
|
+
|
|
63
|
+
# Parse trust policy (it might be URL-encoded)
|
|
64
|
+
if isinstance(trust_policy, str):
|
|
65
|
+
trust_policy = json.loads(urllib.parse.unquote(trust_policy))
|
|
66
|
+
|
|
67
|
+
# Check if bedrock-agentcore service can assume this role
|
|
68
|
+
for statement in trust_policy.get("Statement", []):
|
|
69
|
+
if statement.get("Effect") == "Allow":
|
|
70
|
+
principals = statement.get("Principal", {})
|
|
71
|
+
|
|
72
|
+
if isinstance(principals, dict):
|
|
73
|
+
services = principals.get("Service", [])
|
|
74
|
+
if isinstance(services, str):
|
|
75
|
+
services = [services]
|
|
76
|
+
|
|
77
|
+
if "bedrock-agentcore.amazonaws.com" in services:
|
|
78
|
+
return True
|
|
79
|
+
|
|
80
|
+
return False
|
|
81
|
+
|
|
82
|
+
except ClientError as e:
|
|
83
|
+
if e.response["Error"]["Code"] == "NoSuchEntity":
|
|
84
|
+
return False
|
|
85
|
+
raise
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def _ensure_execution_role(agent_config, project_config, config_path, agent_name, region, account_id):
|
|
89
|
+
"""Ensure execution role exists without waiting.
|
|
90
|
+
|
|
91
|
+
This function handles:
|
|
92
|
+
1. Reusing existing role from config if available
|
|
93
|
+
2. Creating role if needed (auto_create_execution_role=True) - now idempotent
|
|
94
|
+
3. Basic validation that existing roles have correct trust policy
|
|
95
|
+
4. Returning role ARN (readiness will be checked during actual deployment)
|
|
96
|
+
"""
|
|
97
|
+
execution_role_arn = agent_config.aws.execution_role
|
|
98
|
+
session = boto3.Session(region_name=region)
|
|
99
|
+
|
|
100
|
+
# Step 1: Check if we already have a role in config
|
|
101
|
+
if execution_role_arn:
|
|
102
|
+
log.info("Using execution role from config: %s", execution_role_arn)
|
|
103
|
+
|
|
104
|
+
# Step 2: Basic validation for existing roles
|
|
105
|
+
if not _validate_execution_role(execution_role_arn, session):
|
|
106
|
+
raise ValueError(
|
|
107
|
+
f"Execution role {execution_role_arn} has invalid trust policy. "
|
|
108
|
+
"Ensure it allows bedrock-agentcore.amazonaws.com service to assume the role."
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
log.info("✅ Execution role validation passed: %s", execution_role_arn)
|
|
112
|
+
return execution_role_arn
|
|
113
|
+
|
|
114
|
+
# Step 3: Create role if needed (idempotent)
|
|
115
|
+
if agent_config.aws.execution_role_auto_create:
|
|
116
|
+
execution_role_arn = get_or_create_runtime_execution_role(
|
|
117
|
+
session=session,
|
|
118
|
+
logger=log,
|
|
119
|
+
region=region,
|
|
120
|
+
account_id=account_id,
|
|
121
|
+
agent_name=agent_name,
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
# Update the config
|
|
125
|
+
agent_config.aws.execution_role = execution_role_arn
|
|
126
|
+
agent_config.aws.execution_role_auto_create = False
|
|
127
|
+
|
|
128
|
+
# Update the project config and save
|
|
129
|
+
project_config.agents[agent_config.name] = agent_config
|
|
130
|
+
save_config(project_config, config_path)
|
|
131
|
+
|
|
132
|
+
log.info("✅ Execution role available: %s", execution_role_arn)
|
|
133
|
+
return execution_role_arn
|
|
134
|
+
|
|
135
|
+
# Step 4: No role and auto-create disabled
|
|
136
|
+
raise ValueError("Execution role not configured and auto-create not enabled")
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def _deploy_to_bedrock_agentcore(
|
|
140
|
+
agent_config, project_config, config_path, agent_name, ecr_uri, region, env_vars=None, auto_update_on_conflict=False
|
|
141
|
+
):
|
|
142
|
+
"""Deploy agent to Bedrock AgentCore with retry logic for role validation."""
|
|
143
|
+
log.info("Deploying to Bedrock AgentCore...")
|
|
144
|
+
|
|
145
|
+
bedrock_agentcore_client = BedrockAgentCoreClient(region)
|
|
146
|
+
|
|
147
|
+
# Transform network configuration to AWS API format
|
|
148
|
+
network_config = agent_config.aws.network_configuration.to_aws_dict()
|
|
149
|
+
protocol_config = agent_config.aws.protocol_configuration.to_aws_dict()
|
|
150
|
+
|
|
151
|
+
# Execution role should be available by now (either provided or auto-created)
|
|
152
|
+
if not agent_config.aws.execution_role:
|
|
153
|
+
raise ValueError(
|
|
154
|
+
"Execution role not available. This should have been handled by _ensure_execution_role. "
|
|
155
|
+
"Please check configuration or enable auto-creation."
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
# Retry logic for role validation eventual consistency
|
|
159
|
+
max_retries = 3
|
|
160
|
+
base_delay = 5 # Start with 2 seconds
|
|
161
|
+
max_delay = 15 # Max 32 seconds between retries
|
|
162
|
+
|
|
163
|
+
for attempt in range(max_retries + 1):
|
|
164
|
+
try:
|
|
165
|
+
agent_info = bedrock_agentcore_client.create_or_update_agent(
|
|
166
|
+
agent_id=agent_config.bedrock_agentcore.agent_id,
|
|
167
|
+
agent_name=agent_name,
|
|
168
|
+
image_uri=f"{ecr_uri}:latest",
|
|
169
|
+
execution_role_arn=agent_config.aws.execution_role,
|
|
170
|
+
network_config=network_config,
|
|
171
|
+
authorizer_config=agent_config.get_authorizer_configuration(),
|
|
172
|
+
protocol_config=protocol_config,
|
|
173
|
+
env_vars=env_vars,
|
|
174
|
+
auto_update_on_conflict=auto_update_on_conflict,
|
|
175
|
+
)
|
|
176
|
+
break # Success! Exit retry loop
|
|
177
|
+
|
|
178
|
+
except ClientError as e:
|
|
179
|
+
error_code = e.response.get("Error", {}).get("Code", "")
|
|
180
|
+
error_message = e.response.get("Error", {}).get("Message", "")
|
|
181
|
+
|
|
182
|
+
# Check if this is a role validation error
|
|
183
|
+
is_role_validation_error = (
|
|
184
|
+
error_code == "ValidationException"
|
|
185
|
+
and "Role validation failed" in error_message
|
|
186
|
+
and agent_config.aws.execution_role in error_message
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
if not is_role_validation_error or attempt == max_retries:
|
|
190
|
+
# Not a role validation error, or we've exhausted retries
|
|
191
|
+
if is_role_validation_error:
|
|
192
|
+
log.error(
|
|
193
|
+
"Role validation failed after %d attempts. The execution role may not be ready. Role: %s",
|
|
194
|
+
max_retries + 1,
|
|
195
|
+
agent_config.aws.execution_role,
|
|
196
|
+
)
|
|
197
|
+
raise e
|
|
198
|
+
|
|
199
|
+
# Calculate delay with exponential backoff
|
|
200
|
+
delay = min(base_delay * (2**attempt), max_delay)
|
|
201
|
+
log.info(
|
|
202
|
+
"⏳ Role validation failed (attempt %d/%d), retrying in %ds... Role: %s",
|
|
203
|
+
attempt + 1,
|
|
204
|
+
max_retries + 1,
|
|
205
|
+
delay,
|
|
206
|
+
agent_config.aws.execution_role,
|
|
207
|
+
)
|
|
208
|
+
time.sleep(delay)
|
|
209
|
+
|
|
210
|
+
# Save deployment info
|
|
211
|
+
agent_id = agent_info["id"]
|
|
212
|
+
agent_arn = agent_info["arn"]
|
|
213
|
+
|
|
214
|
+
# Update the config
|
|
215
|
+
agent_config.bedrock_agentcore.agent_id = agent_id
|
|
216
|
+
agent_config.bedrock_agentcore.agent_arn = agent_arn
|
|
217
|
+
|
|
218
|
+
# Update the project config and save
|
|
219
|
+
project_config.agents[agent_config.name] = agent_config
|
|
220
|
+
save_config(project_config, config_path)
|
|
221
|
+
|
|
222
|
+
log.info("✅ Agent created/updated: %s", agent_arn)
|
|
223
|
+
|
|
224
|
+
# Wait for agent to be ready
|
|
225
|
+
log.info("Polling for endpoint to be ready...")
|
|
226
|
+
result = bedrock_agentcore_client.wait_for_agent_endpoint_ready(agent_id)
|
|
227
|
+
log.info("Agent endpoint: %s", result)
|
|
228
|
+
|
|
229
|
+
return agent_id, agent_arn
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
def launch_bedrock_agentcore(
|
|
233
|
+
config_path: Path,
|
|
234
|
+
agent_name: Optional[str] = None,
|
|
235
|
+
local: bool = False,
|
|
236
|
+
push_ecr_only: bool = False,
|
|
237
|
+
use_codebuild: bool = False,
|
|
238
|
+
env_vars: Optional[dict] = None,
|
|
239
|
+
auto_update_on_conflict: bool = False,
|
|
240
|
+
) -> LaunchResult:
|
|
241
|
+
"""Launch Bedrock AgentCore locally or to cloud.
|
|
242
|
+
|
|
243
|
+
Args:
|
|
244
|
+
config_path: Path to BedrockAgentCore configuration file
|
|
245
|
+
agent_name: Name of agent to launch (for project configurations)
|
|
246
|
+
local: Whether to run locally
|
|
247
|
+
push_ecr_only: Whether to only build and push to ECR without deploying
|
|
248
|
+
use_codebuild: Whether to use CodeBuild for ARM64 builds
|
|
249
|
+
env_vars: Environment variables to pass to local container (dict of key-value pairs)
|
|
250
|
+
auto_update_on_conflict: Whether to automatically update when agent already exists (default: False)
|
|
251
|
+
|
|
252
|
+
Returns:
|
|
253
|
+
LaunchResult model with launch details
|
|
254
|
+
"""
|
|
255
|
+
# Load project configuration
|
|
256
|
+
project_config = load_config(config_path)
|
|
257
|
+
agent_config = project_config.get_agent_config(agent_name)
|
|
258
|
+
|
|
259
|
+
# Handle CodeBuild deployment
|
|
260
|
+
if use_codebuild:
|
|
261
|
+
return _launch_with_codebuild(
|
|
262
|
+
config_path=config_path,
|
|
263
|
+
agent_name=agent_config.name,
|
|
264
|
+
agent_config=agent_config,
|
|
265
|
+
project_config=project_config,
|
|
266
|
+
auto_update_on_conflict=auto_update_on_conflict,
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
# Log which agent is being launched
|
|
270
|
+
mode = "locally" if local else "to ECR only" if push_ecr_only else "to cloud"
|
|
271
|
+
log.info("Launching Bedrock AgentCore agent '%s' %s", agent_config.name, mode)
|
|
272
|
+
|
|
273
|
+
# Validate configuration
|
|
274
|
+
errors = agent_config.validate(for_local=local)
|
|
275
|
+
if errors:
|
|
276
|
+
raise ValueError(f"Invalid configuration: {', '.join(errors)}")
|
|
277
|
+
|
|
278
|
+
# Initialize container runtime
|
|
279
|
+
runtime = ContainerRuntime(agent_config.container_runtime)
|
|
280
|
+
|
|
281
|
+
# Get build context - always use project root (where config and Dockerfile are)
|
|
282
|
+
build_dir = config_path.parent
|
|
283
|
+
|
|
284
|
+
bedrock_agentcore_name = agent_config.name
|
|
285
|
+
tag = f"bedrock_agentcore-{bedrock_agentcore_name}:latest"
|
|
286
|
+
|
|
287
|
+
# Step 1: Build Docker image
|
|
288
|
+
success, output = runtime.build(build_dir, tag)
|
|
289
|
+
if not success:
|
|
290
|
+
error_lines = output[-10:] if len(output) > 10 else output
|
|
291
|
+
raise RuntimeError(f"Build failed: {' '.join(error_lines)}")
|
|
292
|
+
|
|
293
|
+
log.info("Docker image built: %s", tag)
|
|
294
|
+
|
|
295
|
+
if local:
|
|
296
|
+
# Return info for local deployment
|
|
297
|
+
return LaunchResult(
|
|
298
|
+
mode="local",
|
|
299
|
+
tag=tag,
|
|
300
|
+
port=8080,
|
|
301
|
+
runtime=runtime,
|
|
302
|
+
env_vars=env_vars,
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
region = agent_config.aws.region
|
|
306
|
+
if not region:
|
|
307
|
+
raise ValueError("Region not found in configuration")
|
|
308
|
+
|
|
309
|
+
account_id = agent_config.aws.account
|
|
310
|
+
|
|
311
|
+
# Step 2: Ensure execution role exists (moved before ECR push)
|
|
312
|
+
_ensure_execution_role(agent_config, project_config, config_path, bedrock_agentcore_name, region, account_id)
|
|
313
|
+
|
|
314
|
+
# Step 3: Push to ECR
|
|
315
|
+
log.info("Uploading to ECR...")
|
|
316
|
+
|
|
317
|
+
# Handle ECR repository
|
|
318
|
+
ecr_uri = _ensure_ecr_repository(agent_config, project_config, config_path, bedrock_agentcore_name, region)
|
|
319
|
+
|
|
320
|
+
# Deploy to ECR
|
|
321
|
+
repo_name = ecr_uri.split("/")[-1]
|
|
322
|
+
deploy_to_ecr(tag, repo_name, region, runtime)
|
|
323
|
+
|
|
324
|
+
log.info("Image uploaded to ECR: %s", ecr_uri)
|
|
325
|
+
|
|
326
|
+
# If push_ecr_only, return early
|
|
327
|
+
if push_ecr_only:
|
|
328
|
+
return LaunchResult(
|
|
329
|
+
mode="push-ecr",
|
|
330
|
+
tag=tag,
|
|
331
|
+
ecr_uri=ecr_uri,
|
|
332
|
+
build_output=output,
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
# Step 4: Deploy agent (with retry logic for role readiness)
|
|
336
|
+
agent_id, agent_arn = _deploy_to_bedrock_agentcore(
|
|
337
|
+
agent_config,
|
|
338
|
+
project_config,
|
|
339
|
+
config_path,
|
|
340
|
+
bedrock_agentcore_name,
|
|
341
|
+
ecr_uri,
|
|
342
|
+
region,
|
|
343
|
+
env_vars,
|
|
344
|
+
auto_update_on_conflict,
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
return LaunchResult(
|
|
348
|
+
mode="cloud",
|
|
349
|
+
tag=tag,
|
|
350
|
+
agent_arn=agent_arn,
|
|
351
|
+
agent_id=agent_id,
|
|
352
|
+
ecr_uri=ecr_uri,
|
|
353
|
+
build_output=output,
|
|
354
|
+
)
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
def _launch_with_codebuild(
|
|
358
|
+
config_path: Path,
|
|
359
|
+
agent_name: str,
|
|
360
|
+
agent_config,
|
|
361
|
+
project_config,
|
|
362
|
+
auto_update_on_conflict: bool = False,
|
|
363
|
+
) -> LaunchResult:
|
|
364
|
+
"""Launch using CodeBuild for ARM64 builds."""
|
|
365
|
+
log.info(
|
|
366
|
+
"Starting CodeBuild ARM64 deployment for agent '%s' to account %s (%s)",
|
|
367
|
+
agent_name,
|
|
368
|
+
agent_config.aws.account,
|
|
369
|
+
agent_config.aws.region,
|
|
370
|
+
)
|
|
371
|
+
|
|
372
|
+
# Validate configuration
|
|
373
|
+
errors = agent_config.validate(for_local=False)
|
|
374
|
+
if errors:
|
|
375
|
+
raise ValueError(f"Invalid configuration: {', '.join(errors)}")
|
|
376
|
+
|
|
377
|
+
region = agent_config.aws.region
|
|
378
|
+
if not region:
|
|
379
|
+
raise ValueError("Region not found in configuration")
|
|
380
|
+
|
|
381
|
+
session = boto3.Session(region_name=region)
|
|
382
|
+
account_id = agent_config.aws.account # Use existing account from config
|
|
383
|
+
|
|
384
|
+
# Step 1: Setup AWS resources
|
|
385
|
+
log.info("Setting up AWS resources (ECR repository, execution roles)...")
|
|
386
|
+
ecr_uri = _ensure_ecr_repository(agent_config, project_config, config_path, agent_name, region)
|
|
387
|
+
ecr_repository_arn = f"arn:aws:ecr:{region}:{account_id}:repository/{ecr_uri.split('/')[-1]}"
|
|
388
|
+
_ensure_execution_role(agent_config, project_config, config_path, agent_name, region, account_id)
|
|
389
|
+
|
|
390
|
+
# Step 2: Prepare CodeBuild
|
|
391
|
+
log.info("Preparing CodeBuild project and uploading source...")
|
|
392
|
+
codebuild_service = CodeBuildService(session)
|
|
393
|
+
|
|
394
|
+
codebuild_execution_role = codebuild_service.create_codebuild_execution_role(
|
|
395
|
+
account_id=account_id, ecr_repository_arn=ecr_repository_arn, agent_name=agent_name
|
|
396
|
+
)
|
|
397
|
+
|
|
398
|
+
source_location = codebuild_service.upload_source(agent_name=agent_name)
|
|
399
|
+
|
|
400
|
+
project_name = codebuild_service.create_or_update_project(
|
|
401
|
+
agent_name=agent_name,
|
|
402
|
+
ecr_repository_uri=ecr_uri,
|
|
403
|
+
execution_role=codebuild_execution_role,
|
|
404
|
+
source_location=source_location,
|
|
405
|
+
)
|
|
406
|
+
|
|
407
|
+
# Step 3: Execute CodeBuild
|
|
408
|
+
log.info("Starting CodeBuild build (this may take several minutes)...")
|
|
409
|
+
build_id = codebuild_service.start_build(project_name, source_location)
|
|
410
|
+
codebuild_service.wait_for_completion(build_id)
|
|
411
|
+
log.info("CodeBuild completed successfully")
|
|
412
|
+
|
|
413
|
+
# Update CodeBuild config
|
|
414
|
+
agent_config.codebuild.project_name = project_name
|
|
415
|
+
agent_config.codebuild.execution_role = codebuild_execution_role
|
|
416
|
+
agent_config.codebuild.source_bucket = codebuild_service.source_bucket
|
|
417
|
+
|
|
418
|
+
# Deploy to Bedrock AgentCore
|
|
419
|
+
agent_id, agent_arn = _deploy_to_bedrock_agentcore(
|
|
420
|
+
agent_config,
|
|
421
|
+
project_config,
|
|
422
|
+
config_path,
|
|
423
|
+
agent_name,
|
|
424
|
+
ecr_uri,
|
|
425
|
+
region,
|
|
426
|
+
env_vars=None,
|
|
427
|
+
auto_update_on_conflict=auto_update_on_conflict,
|
|
428
|
+
)
|
|
429
|
+
|
|
430
|
+
log.info("Deployment completed successfully - Agent: %s", agent_arn)
|
|
431
|
+
|
|
432
|
+
return LaunchResult(
|
|
433
|
+
mode="codebuild",
|
|
434
|
+
tag=f"bedrock_agentcore-{agent_name}:latest",
|
|
435
|
+
codebuild_id=build_id,
|
|
436
|
+
ecr_uri=ecr_uri,
|
|
437
|
+
agent_arn=agent_arn,
|
|
438
|
+
agent_id=agent_id,
|
|
439
|
+
)
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"""Pydantic models for operation requests and responses."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Any, Dict, List, Optional
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
7
|
+
|
|
8
|
+
from ...utils.runtime.container import ContainerRuntime
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# Configure operation models
|
|
12
|
+
class ConfigureResult(BaseModel):
|
|
13
|
+
"""Result of configure operation."""
|
|
14
|
+
|
|
15
|
+
config_path: Path = Field(..., description="Path to configuration file")
|
|
16
|
+
dockerfile_path: Path = Field(..., description="Path to generated Dockerfile")
|
|
17
|
+
dockerignore_path: Optional[Path] = Field(None, description="Path to generated .dockerignore")
|
|
18
|
+
runtime: str = Field(..., description="Container runtime name")
|
|
19
|
+
region: str = Field(..., description="AWS region")
|
|
20
|
+
account_id: str = Field(..., description="AWS account ID")
|
|
21
|
+
execution_role: Optional[str] = Field(None, description="AWS execution role ARN")
|
|
22
|
+
ecr_repository: Optional[str] = Field(None, description="ECR repository URI")
|
|
23
|
+
auto_create_ecr: bool = Field(False, description="Whether ECR will be auto-created")
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# Launch operation models
|
|
27
|
+
class LaunchResult(BaseModel):
|
|
28
|
+
"""Result of launch operation."""
|
|
29
|
+
|
|
30
|
+
mode: str = Field(..., description="Launch mode: local, push-ecr, cloud, or codebuild")
|
|
31
|
+
tag: str = Field(..., description="Docker image tag")
|
|
32
|
+
env_vars: Optional[Dict[str, str]] = Field(default=None, description="Environment variables for local deployment")
|
|
33
|
+
|
|
34
|
+
# Local mode fields
|
|
35
|
+
port: Optional[int] = Field(default=None, description="Port for local deployment")
|
|
36
|
+
runtime: Optional[ContainerRuntime] = Field(default=None, description="Container runtime instance")
|
|
37
|
+
|
|
38
|
+
# Cloud mode fields
|
|
39
|
+
ecr_uri: Optional[str] = Field(default=None, description="ECR repository URI")
|
|
40
|
+
agent_id: Optional[str] = Field(default=None, description="BedrockAgentCore agent ID")
|
|
41
|
+
agent_arn: Optional[str] = Field(default=None, description="BedrockAgentCore agent ARN")
|
|
42
|
+
|
|
43
|
+
# CodeBuild mode fields
|
|
44
|
+
codebuild_id: Optional[str] = Field(default=None, description="CodeBuild build ID for ARM64 builds")
|
|
45
|
+
|
|
46
|
+
# Build output (optional)
|
|
47
|
+
build_output: Optional[List[str]] = Field(default=None, description="Docker build output")
|
|
48
|
+
|
|
49
|
+
model_config = ConfigDict(arbitrary_types_allowed=True) # For runtime field
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class InvokeResult(BaseModel):
|
|
53
|
+
"""Result of invoke operation."""
|
|
54
|
+
|
|
55
|
+
response: Dict[str, Any] = Field(..., description="Response from Bedrock AgentCore endpoint")
|
|
56
|
+
session_id: str = Field(..., description="Session ID used for invocation")
|
|
57
|
+
agent_arn: Optional[str] = Field(default=None, description="BedrockAgentCore agent ARN")
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
# Status operation models
|
|
61
|
+
class StatusConfigInfo(BaseModel):
|
|
62
|
+
"""Configuration information for status."""
|
|
63
|
+
|
|
64
|
+
name: str = Field(..., description="Bedrock AgentCore application name")
|
|
65
|
+
entrypoint: str = Field(..., description="Entrypoint file path")
|
|
66
|
+
region: Optional[str] = Field(None, description="AWS region")
|
|
67
|
+
account: Optional[str] = Field(None, description="AWS account ID")
|
|
68
|
+
execution_role: Optional[str] = Field(None, description="AWS execution role ARN")
|
|
69
|
+
ecr_repository: Optional[str] = Field(None, description="ECR repository URI")
|
|
70
|
+
agent_id: Optional[str] = Field(None, description="BedrockAgentCore agent ID")
|
|
71
|
+
agent_arn: Optional[str] = Field(None, description="BedrockAgentCore agent ARN")
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class StatusResult(BaseModel):
|
|
75
|
+
"""Result of status operation."""
|
|
76
|
+
|
|
77
|
+
config: StatusConfigInfo = Field(..., description="Configuration information")
|
|
78
|
+
agent: Optional[Dict[str, Any]] = Field(None, description="Agent runtime details or error")
|
|
79
|
+
endpoint: Optional[Dict[str, Any]] = Field(None, description="Endpoint details or error")
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""Status operations for Bedrock AgentCore SDK."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Optional
|
|
5
|
+
|
|
6
|
+
from ...services.runtime import BedrockAgentCoreClient
|
|
7
|
+
from ...utils.runtime.config import load_config
|
|
8
|
+
from .models import StatusConfigInfo, StatusResult
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def get_status(config_path: Path, agent_name: Optional[str] = None) -> StatusResult:
|
|
12
|
+
"""Get Bedrock AgentCore status including config and runtime details.
|
|
13
|
+
|
|
14
|
+
Args:
|
|
15
|
+
config_path: Path to BedrockAgentCore configuration file
|
|
16
|
+
agent_name: Name of agent to get status for (for project configurations)
|
|
17
|
+
|
|
18
|
+
Returns:
|
|
19
|
+
StatusResult with config, agent, and endpoint status
|
|
20
|
+
|
|
21
|
+
Raises:
|
|
22
|
+
FileNotFoundError: If configuration file doesn't exist
|
|
23
|
+
ValueError: If Bedrock AgentCore is not deployed or configuration is invalid
|
|
24
|
+
"""
|
|
25
|
+
# Load project configuration
|
|
26
|
+
project_config = load_config(config_path)
|
|
27
|
+
agent_config = project_config.get_agent_config(agent_name)
|
|
28
|
+
|
|
29
|
+
# Build config info
|
|
30
|
+
config_info = StatusConfigInfo(
|
|
31
|
+
name=agent_config.name,
|
|
32
|
+
entrypoint=agent_config.entrypoint,
|
|
33
|
+
region=agent_config.aws.region,
|
|
34
|
+
account=agent_config.aws.account,
|
|
35
|
+
execution_role=agent_config.aws.execution_role,
|
|
36
|
+
ecr_repository=agent_config.aws.ecr_repository,
|
|
37
|
+
agent_id=agent_config.bedrock_agentcore.agent_id,
|
|
38
|
+
agent_arn=agent_config.bedrock_agentcore.agent_arn,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
# Initialize status result
|
|
42
|
+
agent_details = None
|
|
43
|
+
endpoint_details = None
|
|
44
|
+
|
|
45
|
+
# If agent is deployed, get runtime status
|
|
46
|
+
if agent_config.bedrock_agentcore.agent_id and agent_config.aws.region:
|
|
47
|
+
try:
|
|
48
|
+
client = BedrockAgentCoreClient(agent_config.aws.region)
|
|
49
|
+
|
|
50
|
+
# Get agent runtime details
|
|
51
|
+
try:
|
|
52
|
+
agent_details = client.get_agent_runtime(agent_config.bedrock_agentcore.agent_id)
|
|
53
|
+
except Exception as e:
|
|
54
|
+
agent_details = {"error": str(e)}
|
|
55
|
+
|
|
56
|
+
# Get endpoint details
|
|
57
|
+
try:
|
|
58
|
+
endpoint_details = client.get_agent_runtime_endpoint(agent_config.bedrock_agentcore.agent_id)
|
|
59
|
+
except Exception as e:
|
|
60
|
+
endpoint_details = {"error": str(e)}
|
|
61
|
+
|
|
62
|
+
except Exception as e:
|
|
63
|
+
agent_details = {"error": f"Failed to initialize Bedrock AgentCore client: {e}"}
|
|
64
|
+
endpoint_details = {"error": f"Failed to initialize Bedrock AgentCore client: {e}"}
|
|
65
|
+
|
|
66
|
+
return StatusResult(config=config_info, agent=agent_details, endpoint=endpoint_details)
|