4b6817381b
Benchmark image — build + push to ECR (any adapter) / build + push (push) Waiting to run
CI / quality (ubuntu-latest) (push) Waiting to run
CI / test (tools-runtime) (push) Waiting to run
CI / test (e2e-general) (push) Waiting to run
CI / test (cli-runtime) (push) Waiting to run
CI / test (e2e-provider-and-openclaw) (push) Waiting to run
CI / test (integrations-and-misc) (push) Waiting to run
CI / coverage-report (push) Blocked by required conditions
CI / test-kubernetes (push) Waiting to run
CI / should-run-thorough (push) Waiting to run
CI / test-thorough (cloudwatch-demo) (push) Blocked by required conditions
CI / test-thorough (flink-ecs) (push) Blocked by required conditions
CI / test-thorough (upstream-lambda) (push) Blocked by required conditions
CI / test-thorough (prefect-ecs-fargate) (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Release / build-binaries (zip, opensre.exe, onefile, windows-latest, windows-x64) (push) Blocked by required conditions
Release / publish-release (push) Blocked by required conditions
Release / publish-main-release (push) Blocked by required conditions
Release / prepare (push) Waiting to run
Release / verify (push) Blocked by required conditions
Release / build-python-dist (push) Blocked by required conditions
Release / build-binaries (tar.gz, opensre, onedir, macos-15-intel, darwin-x64) (push) Blocked by required conditions
Release / build-binaries (tar.gz, opensre, onedir, macos-latest, darwin-arm64) (push) Blocked by required conditions
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04, linux-x64) (push) Blocked by required conditions
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04-arm, linux-arm64) (push) Blocked by required conditions
Synthetic Deterministic Tests / Synthetic offline (deterministic) (push) Waiting to run
Interactive Shell Live (PR + post-merge) / turn-checks (no-LLM) (push) Waiting to run
Interactive Shell Live (PR + post-merge) / turn-live shard ${{ matrix.shard_index }} (push) Waiting to run
CI (OpenClaw E2E) / openclaw test (push) Has been cancelled
143 lines
5.0 KiB
Python
143 lines
5.0 KiB
Python
"""Dynamic stack configuration loader.
|
|
|
|
Fetches configuration from CloudFormation stack outputs or SDK outputs.
|
|
No more hardcoded URLs/IPs - single source of truth.
|
|
"""
|
|
|
|
import boto3
|
|
from botocore.exceptions import BotoCoreError, ClientError, NoCredentialsError
|
|
|
|
from tests.shared.infrastructure_sdk.config import load_outputs
|
|
|
|
|
|
def get_sdk_outputs(stack_name: str) -> dict:
|
|
"""Fetch outputs from SDK deployment JSON file.
|
|
|
|
Returns empty dict if outputs file doesn't exist.
|
|
"""
|
|
try:
|
|
return load_outputs(stack_name)
|
|
except FileNotFoundError:
|
|
return {}
|
|
|
|
|
|
def get_stack_outputs(stack_name: str, region: str = "us-east-1") -> dict:
|
|
"""Fetch all outputs from a CloudFormation stack.
|
|
|
|
Returns empty dict if AWS credentials are unavailable (allows test collection).
|
|
"""
|
|
try:
|
|
cf = boto3.client("cloudformation", region_name=region)
|
|
response = cf.describe_stacks(StackName=stack_name)
|
|
outputs = {}
|
|
for output in response["Stacks"][0].get("Outputs", []):
|
|
outputs[output["OutputKey"]] = output["OutputValue"]
|
|
return outputs
|
|
except (NoCredentialsError, BotoCoreError, ClientError):
|
|
# Return empty dict - tests will be skipped when config values are missing
|
|
return {}
|
|
|
|
|
|
def get_ecs_task_public_ip(cluster_name: str, region: str = "us-east-1") -> str | None:
|
|
"""Fetch public IP of a running ECS task (for services without load balancer).
|
|
|
|
Returns None if AWS credentials are unavailable.
|
|
"""
|
|
try:
|
|
ecs = boto3.client("ecs", region_name=region)
|
|
ec2 = boto3.client("ec2", region_name=region)
|
|
|
|
tasks = ecs.list_tasks(cluster=cluster_name, desiredStatus="RUNNING")
|
|
if not tasks.get("taskArns"):
|
|
return None
|
|
|
|
task_details = ecs.describe_tasks(cluster=cluster_name, tasks=tasks["taskArns"])
|
|
for task in task_details.get("tasks", []):
|
|
for attachment in task.get("attachments", []):
|
|
for detail in attachment.get("details", []):
|
|
if detail.get("name") == "networkInterfaceId":
|
|
eni_id = detail.get("value")
|
|
eni = ec2.describe_network_interfaces(NetworkInterfaceIds=[eni_id])
|
|
public_ip = (
|
|
eni["NetworkInterfaces"][0].get("Association", {}).get("PublicIp")
|
|
)
|
|
if public_ip:
|
|
return public_ip
|
|
return None
|
|
except (NoCredentialsError, BotoCoreError, ClientError):
|
|
return None
|
|
|
|
|
|
# Stack configurations
|
|
STACKS = {
|
|
"flink": "TracerFlinkEcs",
|
|
"prefect": "TracerPrefectEcsFargate",
|
|
"lambda": "TracerUpstreamLambda",
|
|
}
|
|
|
|
# SDK stack names (different naming convention)
|
|
SDK_STACKS = {
|
|
"flink": "tracer-flink-ecs",
|
|
"prefect": "tracer-prefect-ecs",
|
|
}
|
|
|
|
|
|
def get_flink_config() -> dict:
|
|
"""Get Flink test configuration from stack outputs.
|
|
|
|
Checks SDK outputs first, then falls back to CloudFormation.
|
|
"""
|
|
# Try SDK outputs first
|
|
outputs = get_sdk_outputs(SDK_STACKS["flink"])
|
|
|
|
# Fall back to CloudFormation if no SDK outputs
|
|
if not outputs:
|
|
outputs = get_stack_outputs(STACKS["flink"])
|
|
|
|
return {
|
|
"trigger_api_url": outputs.get("TriggerApiUrl"),
|
|
"mock_api_url": outputs.get("MockApiUrl"),
|
|
"log_group": outputs.get("LogGroupName"),
|
|
"ecs_cluster": outputs.get("EcsClusterName"),
|
|
"landing_bucket": outputs.get("LandingBucketName"),
|
|
"processed_bucket": outputs.get("ProcessedBucketName"),
|
|
"trigger_lambda": outputs.get("TriggerLambdaName"),
|
|
"mock_api_lambda": outputs.get("MockApiLambdaName"),
|
|
"task_definition_arn": outputs.get("TaskDefinitionArn"),
|
|
"security_group_id": outputs.get("SecurityGroupId"),
|
|
"subnet_ids": outputs.get("SubnetIds"),
|
|
}
|
|
|
|
|
|
def get_prefect_config() -> dict:
|
|
"""Get Prefect test configuration from stack outputs.
|
|
|
|
Checks SDK outputs first (tracer-prefect-ecs), then falls back to CDK stack.
|
|
"""
|
|
# Try SDK outputs first (new deployment method)
|
|
outputs = get_sdk_outputs("tracer-prefect-ecs")
|
|
|
|
# Fall back to CDK stack outputs
|
|
if not outputs:
|
|
outputs = get_stack_outputs(STACKS["prefect"])
|
|
|
|
cluster_name = outputs.get("EcsClusterName")
|
|
prefect_api_url = None
|
|
if cluster_name:
|
|
public_ip = get_ecs_task_public_ip(cluster_name)
|
|
if public_ip:
|
|
prefect_api_url = f"http://{public_ip}:4200/api"
|
|
|
|
return {
|
|
"trigger_api_url": outputs.get("TriggerApiUrl"),
|
|
"mock_api_url": outputs.get("MockApiUrl"),
|
|
"log_group": outputs.get("LogGroupName"),
|
|
"ecs_cluster": cluster_name,
|
|
"prefect_api_url": prefect_api_url,
|
|
"s3_bucket": outputs.get("LandingBucketName"),
|
|
"processed_bucket": outputs.get("ProcessedBucketName"),
|
|
"flow_task_definition": outputs.get("FlowTaskDefinitionArn"),
|
|
"security_group_id": outputs.get("SecurityGroupId"),
|
|
"subnet_ids": outputs.get("SubnetIds"),
|
|
}
|