From f8ee14e0f944c391a501ba88387c16a72935ce99 Mon Sep 17 00:00:00 2001 From: Yoav Katz Date: Thu, 23 Jul 2026 11:38:07 +0300 Subject: [PATCH 1/2] =?UTF-8?q?rename:=20Kagenti=20=E2=86=92=20Rossoctl=20?= =?UTF-8?q?throughout=20scripts=20and=20docs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace all 189 occurrences of kagenti/Kagenti/KAGENTI with rossoctl/Rossoctl/ROSSOCTL across 18 files in exgentic_a2a_runner/. Covers: k8s namespace (rossoctl-system), Keycloak realm/client (rossoctl), kind cluster (kind-rossoctl), shell function names, variable names, API URL patterns, and all prose in docs and comments. Closes rossoctl/workload-harness#43 Signed-off-by: Yoav Katz Co-Authored-By: Claude Sonnet 4.6 (1M context) --- .../AUTHBRIDGE_PIPELINE_SPEC.md | 2 +- .../IMPLEMENTATION_CHECKLIST.md | 8 +- exgentic_a2a_runner/analyze-run.sh | 10 +- .../authbridge/apply-pipeline.sh | 2 +- .../authbridge/pipeline-merge.py | 17 +++ .../authbridge/plugins/token-exchange.yaml | 2 +- exgentic_a2a_runner/delete-all-deployments.sh | 56 ++++----- exgentic_a2a_runner/deploy-agent.sh | 114 +++++++++--------- exgentic_a2a_runner/deploy-benchmark.sh | 114 +++++++++--------- exgentic_a2a_runner/deploy-gsm8k-local.sh | 82 +++++++++++++ exgentic_a2a_runner/docs/workflow-diagrams.md | 32 ++--- exgentic_a2a_runner/evaluate-benchmark.sh | 2 +- .../exgentic_a2a_runner/__init__.py | 4 +- exgentic_a2a_runner/k8s/job.yaml | 4 +- .../libsh/check-kubectl-context.sh | 6 +- exgentic_a2a_runner/libsh/urls.sh | 12 +- exgentic_a2a_runner/pyproject.toml | 2 +- exgentic_a2a_runner/sync-image-to-cluster.sh | 4 +- 18 files changed, 286 insertions(+), 187 deletions(-) create mode 100755 exgentic_a2a_runner/deploy-gsm8k-local.sh diff --git a/exgentic_a2a_runner/AUTHBRIDGE_PIPELINE_SPEC.md b/exgentic_a2a_runner/AUTHBRIDGE_PIPELINE_SPEC.md index e2dfb3a..49f3a86 100644 --- a/exgentic_a2a_runner/AUTHBRIDGE_PIPELINE_SPEC.md +++ b/exgentic_a2a_runner/AUTHBRIDGE_PIPELINE_SPEC.md @@ -30,7 +30,7 @@ This proposal generalizes the deploy scripts so they drive the pipeline by **ena - Backwards compatibility with the previous `--ibac` / `--authbridge` flags or their env-var aliases. They are removed. - Building a full YAML editor in shell. Pipeline ordering rules and slot dependency validation stay in AuthBridge (`pipeline.New`). - Exposing every plugin config field as a CLI flag. We ship sensible defaults; advanced users override via env vars or `--plugin-config-file`. -- Changing the operator. The base config still comes from `kagenti-operator`; we only overlay. +- Changing the operator. The base config still comes from `rossoctl-operator`; we only overlay. ## 3. Proposed CLI surface diff --git a/exgentic_a2a_runner/IMPLEMENTATION_CHECKLIST.md b/exgentic_a2a_runner/IMPLEMENTATION_CHECKLIST.md index cc6a203..631228a 100644 --- a/exgentic_a2a_runner/IMPLEMENTATION_CHECKLIST.md +++ b/exgentic_a2a_runner/IMPLEMENTATION_CHECKLIST.md @@ -180,12 +180,12 @@ The implementation is ready for testing with: - Real Exgentic MCP server -- Kagenti generalist agent +- Rossoctl generalist agent - OTLP collector for telemetry ### To Test: 1. Set up Exgentic MCP server -2. Deploy Kagenti agent with A2A endpoint +2. Deploy Rossoctl agent with A2A endpoint 3. Configure environment variables 4. Run: `uv run exgentic-a2a-runner` 5. Verify session creation, execution, evaluation, and cleanup @@ -196,9 +196,9 @@ The implementation is ready for testing with: All components have been successfully implemented following the requirements from GitHub Issue #963. The harness: - ✅ Integrates with Exgentic MCP server -- ✅ Communicates with Kagenti agents via A2A +- ✅ Communicates with Rossoctl agents via A2A - ✅ Implements the exact execution model specified - ✅ Provides comprehensive observability - ✅ Is fully documented and ready for deployment -The implementation is **COMPLETE** and ready for integration testing with actual Exgentic MCP server and Kagenti agents. \ No newline at end of file +The implementation is **COMPLETE** and ready for integration testing with actual Exgentic MCP server and Rossoctl agents. \ No newline at end of file diff --git a/exgentic_a2a_runner/analyze-run.sh b/exgentic_a2a_runner/analyze-run.sh index 4ae29e1..7a53397 100755 --- a/exgentic_a2a_runner/analyze-run.sh +++ b/exgentic_a2a_runner/analyze-run.sh @@ -61,14 +61,14 @@ Options: --mlflow-port PORT Remote MLflow service port to forward --mlflow-tls MLflow serves HTTPS on the forwarded port --mlflow-workspace NAME Send x-mlflow-workspace header - --auth-mode MODE Token source: secret (kagenti oauth secret) or oc-token (oc whoami -t) + --auth-mode MODE Token source: secret (rossoctl oauth secret) or oc-token (oc whoami -t) -h, --help Show this help message The MLflow location, TLS, workspace, auth mode, and experiment id all DEFAULT from the cluster mode, so a plain --kind or --openshift needs no other flags: --kind --openshift - namespace kagenti-system redhat-ods-applications + namespace rossoctl-system redhat-ods-applications service mlflow mlflow remote port 5000 8443 tls off (http) on (https) @@ -131,9 +131,9 @@ fi # already set the value wins; only unset values fall back to the mode default. case "$CLUSTER_MODE" in kind) - # kagenti's kind MLflow: HTTP on port 5000 in kagenti-system, no + # rossoctl's kind MLflow: HTTP on port 5000 in rossoctl-system, no # workspace header, client-credentials secret flow for auth. - MLFLOW_NAMESPACE="${MLFLOW_NAMESPACE:-kagenti-system}" + MLFLOW_NAMESPACE="${MLFLOW_NAMESPACE:-rossoctl-system}" MLFLOW_SERVICE="${MLFLOW_SERVICE:-mlflow}" MLFLOW_REMOTE_PORT="${MLFLOW_REMOTE_PORT:-5000}" MLFLOW_TLS="${MLFLOW_TLS:-false}" @@ -277,7 +277,7 @@ cleanup_port_forward() { fi } -# secret mode: kagenti's client-credentials flow. Reads mlflow-oauth-secret and +# secret mode: rossoctl's client-credentials flow. Reads mlflow-oauth-secret and # execs into the MLflow pod to exchange it for an access token. get_token_from_secret() { echo "Obtaining OAuth token via mlflow-oauth-secret..." diff --git a/exgentic_a2a_runner/authbridge/apply-pipeline.sh b/exgentic_a2a_runner/authbridge/apply-pipeline.sh index 0c556c9..3847229 100755 --- a/exgentic_a2a_runner/authbridge/apply-pipeline.sh +++ b/exgentic_a2a_runner/authbridge/apply-pipeline.sh @@ -87,7 +87,7 @@ fi # --- Pre-flight: ConfigMap exists. if ! kubectl -n "$NAMESPACE" get configmap "$CM_NAME" >/dev/null 2>&1; then echo "ERROR: ConfigMap $NAMESPACE/$CM_NAME not found." >&2 - echo " The kagenti operator should create this when the agent pod is admitted." >&2 + echo " The rossoctl operator should create this when the agent pod is admitted." >&2 echo " Check: kubectl -n $NAMESPACE get pods -l app.kubernetes.io/name=$AGENT_NAME" >&2 exit 1 fi diff --git a/exgentic_a2a_runner/authbridge/pipeline-merge.py b/exgentic_a2a_runner/authbridge/pipeline-merge.py index a0e7d3b..ebfdc56 100755 --- a/exgentic_a2a_runner/authbridge/pipeline-merge.py +++ b/exgentic_a2a_runner/authbridge/pipeline-merge.py @@ -236,6 +236,23 @@ def main() -> int: pipeline.setdefault("inbound", {})["plugins"] = inbound_entries pipeline.setdefault("outbound", {})["plugins"] = outbound_entries + # Ensure the OTEL collector bypasses the authbridge listener. Without this + # the proxy intercepts OTLP egress and resets the connection, which the + # exgentic library misreports as "Protocol mismatch" causing a crash-loop + # (issue #34). We add both the FQDN and the short name in case the exporter + # ever resolves via the short form. + otel_skip = [ + "otel-collector.rossoctl-system.svc.cluster.local", + "otel-collector", + ] + listener = operator.setdefault("listener", {}) + existing = listener.get("skip_hosts") or [] + merged_skip = list(existing) + for host in otel_skip: + if host not in merged_skip: + merged_skip.append(host) + listener["skip_hosts"] = merged_skip + sys.stdout.write( yaml.safe_dump(operator, default_flow_style=False, sort_keys=False) ) diff --git a/exgentic_a2a_runner/authbridge/plugins/token-exchange.yaml b/exgentic_a2a_runner/authbridge/plugins/token-exchange.yaml index 2651239..d583adf 100644 --- a/exgentic_a2a_runner/authbridge/plugins/token-exchange.yaml +++ b/exgentic_a2a_runner/authbridge/plugins/token-exchange.yaml @@ -4,7 +4,7 @@ # This fragment is intentionally minimal so the overlay can keep the # plugin in the resolved selection without re-rendering the operator # config. Per-route exchange rules live in the `authproxy-routes` -# ConfigMap (see kagenti-extensions/authbridge/CLAUDE.md). Per-plugin +# ConfigMap (see rossoctl-extensions/authbridge/CLAUDE.md). Per-plugin # overrides may be supplied via --plugin-config-file. # # Mutually exclusive with token-broker (both claim diff --git a/exgentic_a2a_runner/delete-all-deployments.sh b/exgentic_a2a_runner/delete-all-deployments.sh index 3f32e93..2d664fc 100755 --- a/exgentic_a2a_runner/delete-all-deployments.sh +++ b/exgentic_a2a_runner/delete-all-deployments.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Delete all agent and benchmark (tool) deployments from a Kagenti namespace via the API. +# Delete all agent and benchmark (tool) deployments from a Rossoctl namespace via the API. # Usage: ./delete-all-deployments.sh [OPTIONS] # Example: ./delete-all-deployments.sh --openshift apps.mycluster.example.com # Example: ./delete-all-deployments.sh --kind @@ -37,7 +37,7 @@ usage() { cat < Kagenti namespace (default: team1) + --namespace Rossoctl namespace (default: team1) --keycloak-user Keycloak username (default: admin) --keycloak-pass Keycloak password (overrides KEYCLOAK_PASSWORD env) --dry-run List what would be deleted without deleting anything @@ -102,14 +102,14 @@ source "$SCRIPT_DIR/libsh/urls.sh" source "$SCRIPT_DIR/libsh/check-kubectl-context.sh" check_kubectl_context -KAGENTI_API="$(kagenti_api_url)" +ROSSOCTL_API="$(rossoctl_api_url)" KEYCLOAK_API="$(keycloak_api_url)" echo "==========================================" echo " Delete All Deployments" echo "==========================================" echo " Namespace: $NAMESPACE" -echo " Kagenti API: $KAGENTI_API" +echo " Rossoctl API: $ROSSOCTL_API" echo " Dry run: $DRY_RUN" echo "==========================================" echo "" @@ -119,28 +119,28 @@ echo "Step 1: Getting Keycloak authentication token..." if [ "$KEYCLOAK_PASSWORD" = "unknown" ]; then echo "Step 1.5: Attempting to fetch Keycloak password from cluster..." - KAGENTI_PASSWORD=$("$KUBECTL_BIN" get secret kagenti-test-user -n keycloak -o jsonpath='{.data.password}' 2>/dev/null | base64 -d 2>/dev/null || echo "") - if [ -n "$KAGENTI_PASSWORD" ]; then - TEST_AUTH=$(curl -s -X POST "$KEYCLOAK_API/realms/kagenti/protocol/openid-connect/token" \ + ROSSOCTL_PASSWORD=$("$KUBECTL_BIN" get secret rossoctl-test-user -n keycloak -o jsonpath='{.data.password}' 2>/dev/null | base64 -d 2>/dev/null || echo "") + if [ -n "$ROSSOCTL_PASSWORD" ]; then + TEST_AUTH=$(curl -s -X POST "$KEYCLOAK_API/realms/rossoctl/protocol/openid-connect/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "username=$KEYCLOAK_USERNAME" \ - -d "password=$KAGENTI_PASSWORD" \ + -d "password=$ROSSOCTL_PASSWORD" \ -d "grant_type=password" \ - -d "client_id=kagenti" 2>/dev/null || echo "") + -d "client_id=rossoctl" 2>/dev/null || echo "") if echo "$TEST_AUTH" | grep -q "access_token"; then - KEYCLOAK_PASSWORD="$KAGENTI_PASSWORD" + KEYCLOAK_PASSWORD="$ROSSOCTL_PASSWORD" echo "✓ Fetched Keycloak password from cluster" else echo "⚠ Warning: Fetched password from cluster but authentication failed" exit 1 fi else - TEST_AUTH=$(curl -s -X POST "$KEYCLOAK_API/realms/kagenti/protocol/openid-connect/token" \ + TEST_AUTH=$(curl -s -X POST "$KEYCLOAK_API/realms/rossoctl/protocol/openid-connect/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "username=$KEYCLOAK_USERNAME" \ -d "password=admin" \ -d "grant_type=password" \ - -d "client_id=kagenti" 2>/dev/null || echo "") + -d "client_id=rossoctl" 2>/dev/null || echo "") if echo "$TEST_AUTH" | grep -q "access_token"; then KEYCLOAK_PASSWORD="admin" echo "✓ Using default Keycloak password" @@ -151,12 +151,12 @@ if [ "$KEYCLOAK_PASSWORD" = "unknown" ]; then fi fi -TOKEN_RESPONSE=$(curl -s -X POST "$KEYCLOAK_API/realms/kagenti/protocol/openid-connect/token" \ +TOKEN_RESPONSE=$(curl -s -X POST "$KEYCLOAK_API/realms/rossoctl/protocol/openid-connect/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "username=$KEYCLOAK_USERNAME" \ -d "password=$KEYCLOAK_PASSWORD" \ -d "grant_type=password" \ - -d "client_id=kagenti" || echo "TOKEN_ERROR") + -d "client_id=rossoctl" || echo "TOKEN_ERROR") if [ "$TOKEN_RESPONSE" = "TOKEN_ERROR" ]; then echo "Error: Failed to reach Keycloak at $KEYCLOAK_API" @@ -172,13 +172,13 @@ fi echo "✓ Authentication token obtained" echo "" -# Step 2: Verify Kagenti backend is accessible -echo "Step 2: Verifying Kagenti backend accessibility at $KAGENTI_API..." -if ! curl -s --max-time 10 "$KAGENTI_API/api/v1/namespaces" >/dev/null 2>&1; then - echo "Error: Kagenti backend is not accessible at $KAGENTI_API" +# Step 2: Verify Rossoctl backend is accessible +echo "Step 2: Verifying Rossoctl backend accessibility at $ROSSOCTL_API..." +if ! curl -s --max-time 10 "$ROSSOCTL_API/api/v1/namespaces" >/dev/null 2>&1; then + echo "Error: Rossoctl backend is not accessible at $ROSSOCTL_API" exit 1 fi -echo "✓ Kagenti backend is accessible" +echo "✓ Rossoctl backend is accessible" echo "" # Step 3: Discover deployments via kubectl @@ -222,11 +222,11 @@ wait_for_gone() { local elapsed=0 max=30 code while true; do code=$(curl -s --max-time 5 -o /dev/null -w "%{http_code}" \ - "$KAGENTI_API$api_path" \ + "$ROSSOCTL_API$api_path" \ -H "Authorization: Bearer $ACCESS_TOKEN") || code="000" [ "$code" = "404" ] && echo " ✓ $resource_type '$name' confirmed gone" && return 0 if [ "$elapsed" -ge "$max" ]; then - echo " ⚠ $resource_type '$name' still present after ${max}s — Kagenti cleanup stalled" + echo " ⚠ $resource_type '$name' still present after ${max}s — Rossoctl cleanup stalled" return 1 fi sleep 2 @@ -240,15 +240,15 @@ if [ -n "$AGENT_NAMES" ]; then echo "$AGENT_NAMES" | while read -r name; do [ -z "$name" ] && continue echo -n " Deleting agent '$name'... " - HTTP=$(curl -s --max-time 30 -w "%{http_code}" -o /tmp/kagenti_del_agent.txt \ - -X DELETE "$KAGENTI_API/api/v1/agents/$NAMESPACE/$name" \ + HTTP=$(curl -s --max-time 30 -w "%{http_code}" -o /tmp/rossoctl_del_agent.txt \ + -X DELETE "$ROSSOCTL_API/api/v1/agents/$NAMESPACE/$name" \ -H "Authorization: Bearer $ACCESS_TOKEN") || HTTP="000" if [ "$HTTP" = "200" ] || [ "$HTTP" = "404" ]; then echo "done (HTTP $HTTP)" [ "$HTTP" = "200" ] && wait_for_gone "agent" "$name" "/api/v1/agents/$NAMESPACE/$name" else echo "FAILED (HTTP $HTTP)" - cat /tmp/kagenti_del_agent.txt + cat /tmp/rossoctl_del_agent.txt fi done else @@ -262,15 +262,15 @@ if [ -n "$TOOL_NAMES" ]; then echo "$TOOL_NAMES" | while read -r name; do [ -z "$name" ] && continue echo -n " Deleting tool '$name'... " - HTTP=$(curl -s --max-time 30 -w "%{http_code}" -o /tmp/kagenti_del_tool.txt \ - -X DELETE "$KAGENTI_API/api/v1/tools/$NAMESPACE/$name" \ + HTTP=$(curl -s --max-time 30 -w "%{http_code}" -o /tmp/rossoctl_del_tool.txt \ + -X DELETE "$ROSSOCTL_API/api/v1/tools/$NAMESPACE/$name" \ -H "Authorization: Bearer $ACCESS_TOKEN") || HTTP="000" if [ "$HTTP" = "200" ] || [ "$HTTP" = "404" ]; then echo "done (HTTP $HTTP)" [ "$HTTP" = "200" ] && wait_for_gone "tool" "$name" "/api/v1/tools/$NAMESPACE/$name" else echo "FAILED (HTTP $HTTP)" - cat /tmp/kagenti_del_tool.txt + cat /tmp/rossoctl_del_tool.txt fi done else diff --git a/exgentic_a2a_runner/deploy-agent.sh b/exgentic_a2a_runner/deploy-agent.sh index 9326952..86310ed 100755 --- a/exgentic_a2a_runner/deploy-agent.sh +++ b/exgentic_a2a_runner/deploy-agent.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Deploy and Configure agent to Kagenti cluster via API +# Deploy and Configure agent to Rossoctl cluster via API # Usage: ./deploy-agent.sh --benchmark --agent [OPTIONS] # Example: ./deploy-agent.sh --benchmark tau2 --agent tool_calling --model Azure/gpt-4o-mini # Example: ./deploy-agent.sh --benchmark tau2 --agent tool_calling --openshift apps.mycluster.example.com @@ -208,7 +208,7 @@ if [ -n "$EXPERIMENT_NAME" ] && [ "$EXPERIMENT_NAME" != "default" ]; then fi NAMESPACE="${NAMESPACE:-team1}" -# Load shared URL helpers (kagenti_api_url, keycloak_api_url, agent_http_url, …) +# Load shared URL helpers (rossoctl_api_url, keycloak_api_url, agent_http_url, …) export CLUSTER_MODE INGRESS_DOMAIN # shellcheck source=libsh/urls.sh source "$SCRIPT_DIR/libsh/urls.sh" @@ -218,7 +218,7 @@ KUBECTL_BIN="${KUBECTL_BIN:-kubectl}" source "$SCRIPT_DIR/libsh/check-kubectl-context.sh" check_kubectl_context -KAGENTI_API="$(kagenti_api_url)" +ROSSOCTL_API="$(rossoctl_api_url)" KEYCLOAK_API="$(keycloak_api_url)" echo "==========================================" @@ -231,7 +231,7 @@ echo "" # Step 0: Sync local image to cluster if [ "$USE_LOCAL_IMAGE" = "true" ]; then echo "Step 0: Syncing local image to cluster..." - export REMOTE_IMAGE_NAME KIND_CLUSTER_NAME="kagenti" + export REMOTE_IMAGE_NAME KIND_CLUSTER_NAME="rossoctl" source "$(dirname "$0")/sync-image-to-cluster.sh" else echo "Step 0: Syncing local image to cluster... (skipped, K8s will pull from remote registry)" @@ -264,20 +264,20 @@ echo "" if [ "$KEYCLOAK_PASSWORD" = "unknown" ]; then echo "Step 1.5: Attempting to fetch Keycloak password from cluster..." - # Try to get kagenti realm admin credentials from kagenti-test-user secret - KAGENTI_PASSWORD=$(kubectl get secret kagenti-test-user -n keycloak -o jsonpath='{.data.password}' 2>/dev/null | base64 -d 2>/dev/null || echo "") + # Try to get rossoctl realm admin credentials from rossoctl-test-user secret + ROSSOCTL_PASSWORD=$(kubectl get secret rossoctl-test-user -n keycloak -o jsonpath='{.data.password}' 2>/dev/null | base64 -d 2>/dev/null || echo "") - if [ -n "$KAGENTI_PASSWORD" ]; then + if [ -n "$ROSSOCTL_PASSWORD" ]; then # Test if the fetched password works - TEST_AUTH=$(curl -s -X POST "$KEYCLOAK_API/realms/kagenti/protocol/openid-connect/token" \ + TEST_AUTH=$(curl -s -X POST "$KEYCLOAK_API/realms/rossoctl/protocol/openid-connect/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "username=admin" \ - -d "password=$KAGENTI_PASSWORD" \ + -d "password=$ROSSOCTL_PASSWORD" \ -d "grant_type=password" \ - -d "client_id=kagenti" 2>/dev/null || echo "") + -d "client_id=rossoctl" 2>/dev/null || echo "") if echo "$TEST_AUTH" | grep -q "access_token"; then - KEYCLOAK_PASSWORD="$KAGENTI_PASSWORD" + KEYCLOAK_PASSWORD="$ROSSOCTL_PASSWORD" echo "✓ Successfully fetched and verified Keycloak password from cluster" else echo "⚠ Warning: Fetched password from cluster but authentication failed" @@ -286,12 +286,12 @@ if [ "$KEYCLOAK_PASSWORD" = "unknown" ]; then fi else # Fallback: test if default password works - TEST_AUTH=$(curl -s -X POST "$KEYCLOAK_API/realms/kagenti/protocol/openid-connect/token" \ + TEST_AUTH=$(curl -s -X POST "$KEYCLOAK_API/realms/rossoctl/protocol/openid-connect/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "username=admin" \ -d "password=admin" \ -d "grant_type=password" \ - -d "client_id=kagenti" 2>/dev/null || echo "") + -d "client_id=rossoctl" 2>/dev/null || echo "") if echo "$TEST_AUTH" | grep -q "access_token"; then KEYCLOAK_PASSWORD="admin" @@ -305,8 +305,8 @@ if [ "$KEYCLOAK_PASSWORD" = "unknown" ]; then echo "" fi -# Step 2: Enable Direct Access Grants for kagenti client if needed -echo "Step 2: Enabling Direct Access Grants for kagenti client..." +# Step 2: Enable Direct Access Grants for rossoctl client if needed +echo "Step 2: Enabling Direct Access Grants for rossoctl client..." # Get admin token first (use "admin" password for master realm) ADMIN_TOKEN_RESPONSE=$(curl -s -X POST "$KEYCLOAK_API/realms/master/protocol/openid-connect/token" \ @@ -320,19 +320,19 @@ if [ "$ADMIN_TOKEN_RESPONSE" != "TOKEN_ERROR" ]; then ADMIN_TOKEN=$(echo "$ADMIN_TOKEN_RESPONSE" | grep -o '"access_token":"[^"]*"' | sed 's/"access_token":"\([^"]*\)"/\1/') if [ -n "$ADMIN_TOKEN" ]; then - # Get kagenti client configuration - CLIENT_CONFIG=$(curl -s "$KEYCLOAK_API/admin/realms/kagenti/clients?clientId=kagenti" \ + # Get rossoctl client configuration + CLIENT_CONFIG=$(curl -s "$KEYCLOAK_API/admin/realms/rossoctl/clients?clientId=rossoctl" \ -H "Authorization: Bearer $ADMIN_TOKEN" 2>/dev/null) CLIENT_ID=$(echo "$CLIENT_CONFIG" | grep -o '"id":"[^"]*"' | head -1 | sed 's/"id":"\([^"]*\)"/\1/') if [ -n "$CLIENT_ID" ]; then # Enable direct access grants - curl -s -X PUT "$KEYCLOAK_API/admin/realms/kagenti/clients/$CLIENT_ID" \ + curl -s -X PUT "$KEYCLOAK_API/admin/realms/rossoctl/clients/$CLIENT_ID" \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{"directAccessGrantsEnabled": true}' >/dev/null 2>&1 - echo "✓ Direct access grants enabled for kagenti client" + echo "✓ Direct access grants enabled for rossoctl client" fi fi fi @@ -341,12 +341,12 @@ echo "" # Step 2.5: Verify Keycloak password works now that Direct Access Grants is enabled echo "Step 2.5: Verifying Keycloak authentication..." -TEST_AUTH=$(curl -s -X POST "$KEYCLOAK_API/realms/kagenti/protocol/openid-connect/token" \ +TEST_AUTH=$(curl -s -X POST "$KEYCLOAK_API/realms/rossoctl/protocol/openid-connect/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "username=$KEYCLOAK_USERNAME" \ -d "password=$KEYCLOAK_PASSWORD" \ -d "grant_type=password" \ - -d "client_id=kagenti" 2>/dev/null || echo "") + -d "client_id=rossoctl" 2>/dev/null || echo "") if ! echo "$TEST_AUTH" | grep -q "access_token"; then echo "⚠ Warning: Authentication failed with current password" @@ -360,12 +360,12 @@ echo "" # Step 3: Get Keycloak authentication token echo "Step 3: Getting Keycloak authentication token..." -TOKEN_RESPONSE=$(curl -s -X POST "$KEYCLOAK_API/realms/kagenti/protocol/openid-connect/token" \ +TOKEN_RESPONSE=$(curl -s -X POST "$KEYCLOAK_API/realms/rossoctl/protocol/openid-connect/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "username=$KEYCLOAK_USERNAME" \ -d "password=$KEYCLOAK_PASSWORD" \ -d "grant_type=password" \ - -d "client_id=kagenti" || echo "TOKEN_ERROR") + -d "client_id=rossoctl" || echo "TOKEN_ERROR") if [ "$TOKEN_RESPONSE" = "TOKEN_ERROR" ]; then echo "Error: Failed to get authentication token from Keycloak" @@ -378,7 +378,7 @@ if [ -z "$ACCESS_TOKEN" ]; then echo "Error: Failed to extract access token" echo "Response: $TOKEN_RESPONSE" echo "" - echo "If you see 'unauthorized_client' error, the kagenti client may need Direct Access Grants enabled." + echo "If you see 'unauthorized_client' error, the rossoctl client may need Direct Access Grants enabled." echo "You can enable it manually in Keycloak admin console or run this script again." exit 1 fi @@ -387,52 +387,52 @@ echo "✓ Successfully obtained authentication token" echo "" -# Step 4: Verify Kagenti backend is accessible -echo "Step 4: Verifying Kagenti backend accessibility at $KAGENTI_API..." -KAGENTI_REACHABLE=false +# Step 4: Verify Rossoctl backend is accessible +echo "Step 4: Verifying Rossoctl backend accessibility at $ROSSOCTL_API..." +ROSSOCTL_REACHABLE=false for i in $(seq 1 10); do - if curl -s --max-time 5 "$KAGENTI_API/api/v1/namespaces" >/dev/null 2>&1; then - echo "✓ Kagenti backend is accessible" - KAGENTI_REACHABLE=true + if curl -s --max-time 5 "$ROSSOCTL_API/api/v1/namespaces" >/dev/null 2>&1; then + echo "✓ Rossoctl backend is accessible" + ROSSOCTL_REACHABLE=true break fi sleep 1 done -if [ "$KAGENTI_REACHABLE" = false ]; then - echo "Error: Kagenti backend is not accessible at $KAGENTI_API after 10s" - echo "Please ensure Kagenti backend is reachable via HTTP route" +if [ "$ROSSOCTL_REACHABLE" = false ]; then + echo "Error: Rossoctl backend is not accessible at $ROSSOCTL_API after 10s" + echo "Please ensure Rossoctl backend is reachable via HTTP route" exit 1 fi echo "" # Step 5: Delete existing agent if it exists -echo "Step 5: Deleting existing agent via Kagenti API if it exists..." -DELETE_RESPONSE=$(curl -s --max-time 10 -w "%{http_code}" -o /tmp/kagenti_delete_agent_response.txt -X DELETE "$KAGENTI_API/api/v1/agents/$NAMESPACE/$AGENT_NAME" \ +echo "Step 5: Deleting existing agent via Rossoctl API if it exists..." +DELETE_RESPONSE=$(curl -s --max-time 10 -w "%{http_code}" -o /tmp/rossoctl_delete_agent_response.txt -X DELETE "$ROSSOCTL_API/api/v1/agents/$NAMESPACE/$AGENT_NAME" \ -H "Authorization: Bearer $ACCESS_TOKEN") || true if [ -z "$DELETE_RESPONSE" ] || [ "$DELETE_RESPONSE" = "000" ]; then - echo "Error: Could not connect to Kagenti API at $KAGENTI_API" - echo "Please ensure Kagenti backend is accessible via HTTP route" + echo "Error: Could not connect to Rossoctl API at $ROSSOCTL_API" + echo "Please ensure Rossoctl backend is accessible via HTTP route" exit 1 elif [ "$DELETE_RESPONSE" = "200" ] || [ "$DELETE_RESPONSE" = "404" ]; then echo "✓ Agent deleted or did not exist (HTTP $DELETE_RESPONSE)" if [ "$DELETE_RESPONSE" = "200" ]; then - echo "Step 5a: Waiting for Kagenti to finish removing the old agent record..." + echo "Step 5a: Waiting for Rossoctl to finish removing the old agent record..." GONE_WAIT=0 GONE_MAX=30 while true; do CHECK_CODE=$(curl -s --max-time 5 -o /dev/null -w "%{http_code}" \ - "$KAGENTI_API/api/v1/agents/$NAMESPACE/$AGENT_NAME" \ + "$ROSSOCTL_API/api/v1/agents/$NAMESPACE/$AGENT_NAME" \ -H "Authorization: Bearer $ACCESS_TOKEN") || CHECK_CODE="000" if [ "$CHECK_CODE" = "404" ]; then echo "✓ Agent record confirmed gone (HTTP 404)" break fi if [ $GONE_WAIT -ge $GONE_MAX ]; then - echo "Error: Agent record still present after ${GONE_MAX}s — Kagenti cleanup stalled" >&2 + echo "Error: Agent record still present after ${GONE_MAX}s — Rossoctl cleanup stalled" >&2 exit 1 fi sleep 2 @@ -441,12 +441,12 @@ elif [ "$DELETE_RESPONSE" = "200" ] || [ "$DELETE_RESPONSE" = "404" ]; then fi else # Any other status (e.g. 503 upstream/connection errors, 401/403) means the - # Kagenti API is broken or unreachable. Fail fast here rather than warn and + # Rossoctl API is broken or unreachable. Fail fast here rather than warn and # continue into later steps that all hit the same dead backend. echo "Error: Delete returned HTTP $DELETE_RESPONSE" >&2 - echo " Endpoint: $KAGENTI_API/api/v1/agents/$NAMESPACE/$AGENT_NAME" >&2 - echo " Response: $(cat /tmp/kagenti_delete_response.txt)" >&2 - echo " The Kagenti API is not healthy; aborting deployment." >&2 + echo " Endpoint: $ROSSOCTL_API/api/v1/agents/$NAMESPACE/$AGENT_NAME" >&2 + echo " Response: $(cat /tmp/rossoctl_delete_response.txt)" >&2 + echo " The Rossoctl API is not healthy; aborting deployment." >&2 exit 1 fi @@ -465,8 +465,8 @@ if [ -z "$ENV_CONTENT" ] || echo "$ENV_CONTENT" | grep -q "404: Not Found"; then exit 1 fi -# Parse env vars using the Kagenti API -ENV_PARSE_RESPONSE=$(curl -s --max-time 10 -X POST "$KAGENTI_API/api/v1/agents/parse-env" \ +# Parse env vars using the Rossoctl API +ENV_PARSE_RESPONSE=$(curl -s --max-time 10 -X POST "$ROSSOCTL_API/api/v1/agents/parse-env" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -d "{\"content\": $(echo "$ENV_CONTENT" | jq -Rs .)}") || true @@ -514,12 +514,12 @@ if [ "$AGENT_NAME_INPUT" = "tool_calling" ]; then ENV_VARS_WITH_CONFIG=$(echo "$ENV_VARS_WITH_CONFIG" | jq ". + [{\"name\": \"EXGENTIC_SET_AGENT_ENABLE_TOOL_SHORTLISTING\", \"value\": \"true\"}]") fi -# The kagenti-deps otel-collector listens for OTLP/HTTP on 8335 (and gRPC on +# The rossoctl-deps otel-collector listens for OTLP/HTTP on 8335 (and gRPC on # 4317). The receivers ConfigMap shows 4318, but the running collector startup # logs ("Starting HTTP server endpoint: 0.0.0.0:8335") confirm 8335 is what's # actually bound. Working sibling pods (e.g. tau2) also export to 8335. echo "Adding EXGENTIC_OTEL_ENABLED, OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_PROTOCOL" -ENV_VARS_WITH_CONFIG=$(echo "$ENV_VARS_WITH_CONFIG" | jq ". + [{\"name\": \"EXGENTIC_OTEL_ENABLED\", \"value\": \"true\"}, {\"name\": \"OTEL_EXPORTER_OTLP_ENDPOINT\", \"value\": \"http://otel-collector.kagenti-system.svc.cluster.local:8335\"}, {\"name\": \"OTEL_EXPORTER_OTLP_PROTOCOL\", \"value\": \"http/protobuf\"}]") +ENV_VARS_WITH_CONFIG=$(echo "$ENV_VARS_WITH_CONFIG" | jq ". + [{\"name\": \"EXGENTIC_OTEL_ENABLED\", \"value\": \"true\"}, {\"name\": \"OTEL_EXPORTER_OTLP_ENDPOINT\", \"value\": \"http://otel-collector.rossoctl-system.svc.cluster.local:8335\"}, {\"name\": \"OTEL_EXPORTER_OTLP_PROTOCOL\", \"value\": \"http/protobuf\"}]") # Set agent runner to thread for in-process execution (avoids venv subprocess overhead) echo "Adding EXGENTIC_DEFAULT_RUNNER=thread for agent" @@ -535,8 +535,8 @@ ENV_VARS_WITH_CONFIG=$(echo "$ENV_VARS_WITH_CONFIG" | jq ". + [{\"name\": \"LITE echo "✓ Environment variables prepared for deployment" echo "" -# Step 8: Deploy agent via Kagenti API -echo "Step 8: Deploying agent via Kagenti API..." +# Step 8: Deploy agent via Rossoctl API +echo "Step 8: Deploying agent via Rossoctl API..." # Resolve the AuthBridge plugin pipeline from --plugin-preset, --plugin, # --no-plugin, and --plugin-config-file flags. The sidecar is injected @@ -662,29 +662,29 @@ echo "Agent configuration:" echo "$AGENT_JSON" | jq '.' echo "" -HTTP_CODE=$(curl -s --max-time 30 -w "%{http_code}" -o /tmp/kagenti_agent_response.txt -X POST "$KAGENTI_API/api/v1/agents" \ +HTTP_CODE=$(curl -s --max-time 30 -w "%{http_code}" -o /tmp/rossoctl_agent_response.txt -X POST "$ROSSOCTL_API/api/v1/agents" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -d "$AGENT_JSON") || true -RESPONSE=$(cat /tmp/kagenti_agent_response.txt) +RESPONSE=$(cat /tmp/rossoctl_agent_response.txt) echo "API Response (HTTP $HTTP_CODE):" echo "$RESPONSE" echo "" if [ -z "$HTTP_CODE" ] || [ "$HTTP_CODE" = "000" ]; then - echo "Error: Could not connect to Kagenti API at $KAGENTI_API" - echo "Please ensure Kagenti backend is accessible via HTTP route" + echo "Error: Could not connect to Rossoctl API at $ROSSOCTL_API" + echo "Please ensure Rossoctl backend is accessible via HTTP route" exit 1 elif [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then echo "✓ Agent deployment successful" elif [ "$HTTP_CODE" = "409" ]; then - echo "Error: Kagenti API returned 409 — agent still exists after deletion" >&2 + echo "Error: Rossoctl API returned 409 — agent still exists after deletion" >&2 echo " Response: $RESPONSE" >&2 exit 1 else - echo "Error: Kagenti API deployment failed with HTTP $HTTP_CODE" + echo "Error: Rossoctl API deployment failed with HTTP $HTTP_CODE" exit 1 fi @@ -702,7 +702,7 @@ fi echo "" # Step 9.5: Fix route targetPort on OpenShift. -# Kagenti creates the route with targetPort: 8080 (the service port number), but +# Rossoctl creates the route with targetPort: 8080 (the service port number), but # OpenShift resolves targetPort by name when the service port has a name. The # service port is named "http", so "8080" doesn't resolve and the router returns # 503. Patch it to the port name so the route works. diff --git a/exgentic_a2a_runner/deploy-benchmark.sh b/exgentic_a2a_runner/deploy-benchmark.sh index 65cc59f..1b50d29 100755 --- a/exgentic_a2a_runner/deploy-benchmark.sh +++ b/exgentic_a2a_runner/deploy-benchmark.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Deploy and Configure Exgentic benchmark to Kagenti cluster +# Deploy and Configure Exgentic benchmark to Rossoctl cluster # Usage: ./deploy-benchmark.sh --benchmark [OPTIONS] # Example: ./deploy-benchmark.sh --benchmark gsm8k # Example: ./deploy-benchmark.sh --benchmark tau2 --model Azure/gpt-4o-mini @@ -113,7 +113,7 @@ if [ -z "$BENCHMARK_NAME" ]; then exit 1 fi -# Load shared URL helpers (kagenti_api_url, keycloak_api_url, tool_http_url, …) +# Load shared URL helpers (rossoctl_api_url, keycloak_api_url, tool_http_url, …) SCRIPT_DIR_BENCH="$(cd "$(dirname "$0")" && pwd)" export CLUSTER_MODE INGRESS_DOMAIN # shellcheck source=libsh/urls.sh @@ -135,7 +135,7 @@ if [ -n "$EXPERIMENT_NAME" ] && [ "$EXPERIMENT_NAME" != "default" ]; then TOOL_NAME="${TOOL_NAME}-${EXPERIMENT_SUFFIX}" fi NAMESPACE="${NAMESPACE:-team1}" -KAGENTI_API="$(kagenti_api_url)" +ROSSOCTL_API="$(rossoctl_api_url)" KEYCLOAK_API="$(keycloak_api_url)" echo "==========================================" @@ -147,7 +147,7 @@ echo "" # Step 1: Sync local image to cluster if [ "$USE_LOCAL_IMAGE" = "true" ]; then echo "Step 1: Syncing local image to cluster..." - export REMOTE_IMAGE_NAME KIND_CLUSTER_NAME="kagenti" + export REMOTE_IMAGE_NAME KIND_CLUSTER_NAME="rossoctl" source "$(dirname "$0")/sync-image-to-cluster.sh" else echo "Step 1: Syncing local image to cluster... (skipped, K8s will pull from remote registry)" @@ -180,11 +180,11 @@ echo "" if [ "$KEYCLOAK_PASSWORD" = "unknown" ]; then echo "Step 3.5: Fetching Keycloak password from cluster..." - # Try to get kagenti realm admin credentials from kagenti-test-user secret - KAGENTI_PASSWORD=$(kubectl get secret kagenti-test-user -n keycloak -o jsonpath='{.data.password}' 2>/dev/null | base64 -d 2>/dev/null || echo "") + # Try to get rossoctl realm admin credentials from rossoctl-test-user secret + ROSSOCTL_PASSWORD=$(kubectl get secret rossoctl-test-user -n keycloak -o jsonpath='{.data.password}' 2>/dev/null | base64 -d 2>/dev/null || echo "") - if [ -n "$KAGENTI_PASSWORD" ]; then - KEYCLOAK_PASSWORD="$KAGENTI_PASSWORD" + if [ -n "$ROSSOCTL_PASSWORD" ]; then + KEYCLOAK_PASSWORD="$ROSSOCTL_PASSWORD" echo "✓ Fetched Keycloak password from cluster" else echo "⚠ Could not fetch password from cluster, will try default password 'admin'" @@ -193,8 +193,8 @@ if [ "$KEYCLOAK_PASSWORD" = "unknown" ]; then echo "" fi -# Step 4: Enable Direct Access Grants for kagenti client if needed -echo "Step 4: Enabling Direct Access Grants for kagenti client..." +# Step 4: Enable Direct Access Grants for rossoctl client if needed +echo "Step 4: Enabling Direct Access Grants for rossoctl client..." # Resolve master-realm admin credentials: prefer env vars, fall back to the # keycloak-initial-admin secret (RHBK operator), then defaults. @@ -224,39 +224,39 @@ if [ -z "$ADMIN_TOKEN" ]; then exit 1 fi -CLIENT_CONFIG=$(curl -s "$KEYCLOAK_API/admin/realms/kagenti/clients?clientId=kagenti" \ +CLIENT_CONFIG=$(curl -s "$KEYCLOAK_API/admin/realms/rossoctl/clients?clientId=rossoctl" \ -H "Authorization: Bearer $ADMIN_TOKEN" 2>/dev/null) CLIENT_ID=$(echo "$CLIENT_CONFIG" | grep -o '"id":"[^"]*"' | head -1 | sed 's/"id":"\([^"]*\)"/\1/') if [ -z "$CLIENT_ID" ]; then - echo "Error: Could not find kagenti client ID in Keycloak" + echo "Error: Could not find rossoctl client ID in Keycloak" echo " Response: $CLIENT_CONFIG" exit 1 fi PUT_CODE=$(curl -s -o /tmp/kc_put_response.txt -w "%{http_code}" \ - -X PUT "$KEYCLOAK_API/admin/realms/kagenti/clients/$CLIENT_ID" \ + -X PUT "$KEYCLOAK_API/admin/realms/rossoctl/clients/$CLIENT_ID" \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{"directAccessGrantsEnabled": true}' 2>/dev/null) || PUT_CODE="000" if [ "$PUT_CODE" != "204" ] && [ "$PUT_CODE" != "200" ]; then - echo "Error: Failed to enable direct access grants for kagenti client (HTTP $PUT_CODE)" + echo "Error: Failed to enable direct access grants for rossoctl client (HTTP $PUT_CODE)" echo " Response: $(cat /tmp/kc_put_response.txt 2>/dev/null)" exit 1 fi -echo "✓ Direct access grants enabled for kagenti client" +echo "✓ Direct access grants enabled for rossoctl client" echo "" # Step 5: Get Keycloak authentication token... echo "Step 5: Getting Keycloak authentication token..." -# Get token from Keycloak using kagenti client (with direct access grants enabled) -TOKEN_RESPONSE=$(curl -s -X POST "$KEYCLOAK_API/realms/kagenti/protocol/openid-connect/token" \ +# Get token from Keycloak using rossoctl client (with direct access grants enabled) +TOKEN_RESPONSE=$(curl -s -X POST "$KEYCLOAK_API/realms/rossoctl/protocol/openid-connect/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "username=$KEYCLOAK_USERNAME" \ -d "password=$KEYCLOAK_PASSWORD" \ -d "grant_type=password" \ - -d "client_id=kagenti" || echo "TOKEN_ERROR") + -d "client_id=rossoctl" || echo "TOKEN_ERROR") if [ "$TOKEN_RESPONSE" = "TOKEN_ERROR" ]; then echo "Error: Failed to get authentication token from Keycloak" @@ -270,7 +270,7 @@ if [ -z "$ACCESS_TOKEN" ]; then echo "Error: Failed to extract access token from Keycloak response" echo "Response: $TOKEN_RESPONSE" echo "" - echo "If you see 'unauthorized_client' error, the kagenti client may need Direct Access Grants enabled." + echo "If you see 'unauthorized_client' error, the rossoctl client may need Direct Access Grants enabled." echo "You can enable it manually in Keycloak admin console or run this script again." exit 1 fi @@ -279,55 +279,55 @@ echo "✓ Successfully obtained authentication token" echo "" -# Step 6: Verify Kagenti backend is accessible -echo "Step 6: Verifying Kagenti backend accessibility at $KAGENTI_API..." -KAGENTI_REACHABLE=false +# Step 6: Verify Rossoctl backend is accessible +echo "Step 6: Verifying Rossoctl backend accessibility at $ROSSOCTL_API..." +ROSSOCTL_REACHABLE=false for i in $(seq 1 10); do - if curl -s --max-time 5 "$KAGENTI_API/api/v1/namespaces" >/dev/null 2>&1; then - echo "✓ Kagenti backend is accessible" - KAGENTI_REACHABLE=true + if curl -s --max-time 5 "$ROSSOCTL_API/api/v1/namespaces" >/dev/null 2>&1; then + echo "✓ Rossoctl backend is accessible" + ROSSOCTL_REACHABLE=true break fi sleep 1 done -if [ "$KAGENTI_REACHABLE" = false ]; then - echo "Error: Kagenti backend is not accessible at $KAGENTI_API after 10s" - echo "Please ensure Kagenti backend is reachable via HTTP route" +if [ "$ROSSOCTL_REACHABLE" = false ]; then + echo "Error: Rossoctl backend is not accessible at $ROSSOCTL_API after 10s" + echo "Please ensure Rossoctl backend is reachable via HTTP route" exit 1 fi echo "" -# Step 7: Delete existing tool via Kagenti API if it exists -echo "Step 7: Deleting existing tool via Kagenti API if it exists..." -DELETE_RESPONSE=$(curl -s --max-time 10 -w "%{http_code}" -o /tmp/kagenti_delete_response.txt -X DELETE "$KAGENTI_API/api/v1/tools/$NAMESPACE/$TOOL_NAME" \ +# Step 7: Delete existing tool via Rossoctl API if it exists +echo "Step 7: Deleting existing tool via Rossoctl API if it exists..." +DELETE_RESPONSE=$(curl -s --max-time 10 -w "%{http_code}" -o /tmp/rossoctl_delete_response.txt -X DELETE "$ROSSOCTL_API/api/v1/tools/$NAMESPACE/$TOOL_NAME" \ -H "Authorization: Bearer $ACCESS_TOKEN") || true if [ -z "$DELETE_RESPONSE" ] || [ "$DELETE_RESPONSE" = "000" ]; then - echo "Error: Could not connect to Kagenti API at $KAGENTI_API" - echo "Please ensure Kagenti backend is accessible via HTTP route" + echo "Error: Could not connect to Rossoctl API at $ROSSOCTL_API" + echo "Please ensure Rossoctl backend is accessible via HTTP route" exit 1 elif [ "$DELETE_RESPONSE" = "200" ] || [ "$DELETE_RESPONSE" = "404" ]; then echo "✓ Tool deleted or did not exist (HTTP $DELETE_RESPONSE)" - # If the tool existed (200), wait for Kagenti to finish async cleanup before + # If the tool existed (200), wait for Rossoctl to finish async cleanup before # re-creating. A 409 on the subsequent POST means the backend still has the # record; polling here prevents that race. if [ "$DELETE_RESPONSE" = "200" ]; then - echo "Step 7a: Waiting for Kagenti to finish removing the old tool record..." + echo "Step 7a: Waiting for Rossoctl to finish removing the old tool record..." GONE_WAIT=0 GONE_MAX=30 while true; do CHECK_CODE=$(curl -s --max-time 5 -o /dev/null -w "%{http_code}" \ - "$KAGENTI_API/api/v1/tools/$NAMESPACE/$TOOL_NAME" \ + "$ROSSOCTL_API/api/v1/tools/$NAMESPACE/$TOOL_NAME" \ -H "Authorization: Bearer $ACCESS_TOKEN") || CHECK_CODE="000" if [ "$CHECK_CODE" = "404" ]; then echo "✓ Tool record confirmed gone (HTTP 404)" break fi if [ $GONE_WAIT -ge $GONE_MAX ]; then - echo "Error: Tool record still present after ${GONE_MAX}s — Kagenti cleanup stalled" >&2 + echo "Error: Tool record still present after ${GONE_MAX}s — Rossoctl cleanup stalled" >&2 exit 1 fi sleep 2 @@ -336,12 +336,12 @@ elif [ "$DELETE_RESPONSE" = "200" ] || [ "$DELETE_RESPONSE" = "404" ]; then fi else # Any other status (e.g. 503 upstream/connection errors, 401/403) means the - # Kagenti API is broken or unreachable. Fail fast here rather than warn and + # Rossoctl API is broken or unreachable. Fail fast here rather than warn and # continue into later steps that all hit the same dead backend. echo "Error: Delete returned HTTP $DELETE_RESPONSE" >&2 - echo " Endpoint: $KAGENTI_API/api/v1/tools/$NAMESPACE/$TOOL_NAME" >&2 - echo " Response: $(cat /tmp/kagenti_delete_response.txt)" >&2 - echo " The Kagenti API is not healthy; aborting deployment." >&2 + echo " Endpoint: $ROSSOCTL_API/api/v1/tools/$NAMESPACE/$TOOL_NAME" >&2 + echo " Response: $(cat /tmp/rossoctl_delete_response.txt)" >&2 + echo " The Rossoctl API is not healthy; aborting deployment." >&2 exit 1 fi @@ -399,8 +399,8 @@ if [ -z "$ENV_CONTENT" ] || echo "$ENV_CONTENT" | grep -q "404: Not Found"; then exit 1 fi -# Parse env vars using the Kagenti API -ENV_PARSE_RESPONSE=$(curl -s -X POST "$KAGENTI_API/api/v1/agents/parse-env" \ +# Parse env vars using the Rossoctl API +ENV_PARSE_RESPONSE=$(curl -s -X POST "$ROSSOCTL_API/api/v1/agents/parse-env" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -d "{\"content\": $(echo "$ENV_CONTENT" | jq -Rs .)}") @@ -413,7 +413,7 @@ ENV_VARS=$(echo "$ENV_PARSE_RESPONSE" | jq '.envVars' 2>/dev/null) || ENV_VARS=" if [ "$ENV_VARS" = "null" ] || [ -z "$ENV_VARS" ]; then echo "Error: Could not parse environment variables from parse-env API" >&2 - echo " Endpoint: $KAGENTI_API/api/v1/agents/parse-env" >&2 + echo " Endpoint: $ROSSOCTL_API/api/v1/agents/parse-env" >&2 echo " Response: $ENV_PARSE_RESPONSE" >&2 exit 1 fi @@ -445,10 +445,10 @@ fi echo "✓ Environment variables prepared for deployment" echo "" -# Step 9: Deploy tool using Kagenti API -echo "Step 9: Deploying tool via Kagenti API..." +# Step 9: Deploy tool using Rossoctl API +echo "Step 9: Deploying tool via Rossoctl API..." -# Create tool deployment JSON following Kagenti API format +# Create tool deployment JSON following Rossoctl API format TOOL_JSON=$(cat <&2 - echo " This means the delete completed but Kagenti's cleanup is not done." >&2 + echo "Error: Rossoctl API returned 409 — tool still exists after deletion" >&2 + echo " This means the delete completed but Rossoctl's cleanup is not done." >&2 echo " Response: $RESPONSE" >&2 exit 1 else - echo "Error: Kagenti API deployment failed with HTTP $HTTP_CODE" + echo "Error: Rossoctl API deployment failed with HTTP $HTTP_CODE" echo "Response: $RESPONSE" echo "" echo "Please ensure:" - echo " 1. Kagenti API is running at $KAGENTI_API" + echo " 1. Rossoctl API is running at $ROSSOCTL_API" echo " 2. The API endpoint is correct" echo " 3. You have proper permissions" exit 1 @@ -598,7 +598,7 @@ if [ "$USE_MCP_GATEWAY" = "true" ]; then echo "==========================================" echo "" - # Kagenti appends -mcp to the service name + # Rossoctl appends -mcp to the service name MCP_SVC_NAME="${TOOL_NAME}-mcp" if ! kubectl get svc "$MCP_SVC_NAME" -n "$NAMESPACE" >/dev/null 2>&1; then MCP_SVC_NAME="$TOOL_NAME" diff --git a/exgentic_a2a_runner/deploy-gsm8k-local.sh b/exgentic_a2a_runner/deploy-gsm8k-local.sh new file mode 100755 index 0000000..bb6206b --- /dev/null +++ b/exgentic_a2a_runner/deploy-gsm8k-local.sh @@ -0,0 +1,82 @@ +#!/bin/bash +# Minimal manual deploy of the gsm8k benchmark image to the current cluster. +# No Keycloak, no Rossoctl API, no auth — just a Deployment + Service. +# Usage: ./deploy-gsm8k-local.sh + +set -euo pipefail + +# Image (matches deploy-benchmark.sh defaults) +EXGENTIC_REGISTRY="${EXGENTIC_REGISTRY:-ghcr.io/exgentic}" +IMAGE_TAG="${IMAGE_TAG:-latest}" +BENCHMARK_NAME="gsm8k" +IMAGE_NAME="${EXGENTIC_REGISTRY}/exgentic-mcp-${BENCHMARK_NAME}:${IMAGE_TAG}" + +NAMESPACE="${NAMESPACE:-default}" +NAME="exgentic-mcp-${BENCHMARK_NAME}" + +echo "Deploying $NAME" +echo " image: $IMAGE_NAME" +echo " namespace: $NAMESPACE" +echo " context: $(kubectl config current-context)" +echo "" + +if [ "$NAMESPACE" != "default" ]; then + kubectl create namespace "$NAMESPACE" --dry-run=client -o yaml | kubectl apply -f - +fi + +kubectl apply -f - <|Step 2| A[deploy-agent.sh] ORCH -->|Step 3| E[evaluate-benchmark.sh] - B -.->|MCP tool live| K[(Kagenti cluster)] + B -.->|MCP tool live| K[(Rossoctl cluster)] A -.->|A2A agent live| K E -->|runs harness| H[exgentic-a2a-runner] H -.->|MCP + A2A traffic| K @@ -93,8 +93,8 @@ flowchart TD Authenticates to Keycloak (auto-fetching / enabling Direct Access Grants), deletes any existing tool (waiting for async cleanup), fetches + parses the -benchmark `.env` through the Kagenti `parse-env` API, augments it with runtime -vars, then `POST`s a tool spec to the Kagenti API. Polls the MCP `initialize` +benchmark `.env` through the Rossoctl `parse-env` API, augments it with runtime +vars, then `POST`s a tool spec to the Rossoctl API. Polls the MCP `initialize` endpoint until ready. Optionally registers the tool with the MCP Gateway. ### 2.1 Interaction diagram @@ -104,7 +104,7 @@ sequenceDiagram autonumber participant Bench as deploy-benchmark.sh participant KC as Keycloak - participant KAG as Kagenti API + participant KAG as Rossoctl API participant GH as GitHub (raw .env) participant K8s as kubectl / cluster participant MCP as MCP tool pod @@ -112,13 +112,13 @@ sequenceDiagram note over Bench: source libsh/urls.sh → resolve URLs from CLUSTER_MODE Bench->>KC: GET /health (retry ≤10s) opt password == "unknown" (kind) - Bench->>K8s: get secret kagenti-test-user + Bench->>K8s: get secret rossoctl-test-user K8s-->>Bench: benchmark password end Bench->>KC: POST realms/master token (admin-cli) KC-->>Bench: admin token - Bench->>KC: PUT clients/kagenti {directAccessGrantsEnabled:true} - Bench->>KC: POST realms/kagenti token (password grant) + Bench->>KC: PUT clients/rossoctl {directAccessGrantsEnabled:true} + Bench->>KC: POST realms/rossoctl token (password grant) KC-->>Bench: ACCESS_TOKEN Bench->>KAG: GET /api/v1/namespaces (reachability, retry ≤10s) @@ -161,7 +161,7 @@ sequenceDiagram ```mermaid flowchart LR B[deploy-benchmark.sh] -->|auth| KC[(Keycloak)] - B -->|deploy/delete tool
parse-env| KAG[(Kagenti API)] + B -->|deploy/delete tool
parse-env| KAG[(Rossoctl API)] B -->|fetch .env.benchmark| GH[(GitHub raw)] B -->|patch / resources / gateway CRs| KUBE[(kubectl → cluster)] KAG -->|creates Deployment + Service + HTTPRoute| MCP["exgentic-mcp-<bench> pod
team1 ns"] @@ -187,7 +187,7 @@ sequenceDiagram autonumber participant Agent as deploy-agent.sh participant KC as Keycloak - participant KAG as Kagenti API + participant KAG as Rossoctl API participant GH as GitHub (raw .env) participant PY as authbridge resolver (python3) participant K8s as kubectl / cluster @@ -250,7 +250,7 @@ sequenceDiagram ```mermaid flowchart LR A[deploy-agent.sh] -->|auth| KC[(Keycloak)] - A -->|deploy/delete agent
parse-env| KAG[(Kagenti API)] + A -->|deploy/delete agent
parse-env| KAG[(Rossoctl API)] A -->|fetch .env| GH[(GitHub raw)] A -->|resolve pipeline| PY[authbridge resolver.py] A -->|build/patch/secrets/resources| KUBE[(kubectl → cluster)] @@ -374,11 +374,11 @@ flowchart TB R --> PC end - subgraph cluster[Kagenti cluster · namespace team1] + subgraph cluster[Rossoctl cluster · namespace team1] MCP["MCP tool
exgentic-mcp-BENCH"] AG["A2A agent
exgentic-a2a-AGENT-BENCH"] GWY[MCP Gateway
optional] - COL[OTEL collector
kagenti-system] + COL[OTEL collector
rossoctl-system] PROM[Prometheus
istio-system] MLF[(MLflow)] LLM[[LLM endpoint
OPENAI_API_BASE]] @@ -401,11 +401,11 @@ flowchart TB | Helper | `kind` | `openshift` (needs `INGRESS_DOMAIN`) | `in-cluster` | |---|---|---|---| -| `kagenti_api_url` | `kagenti-api.localtest.me:8080` | `kagenti-api-kagenti-system.` | `kagenti-backend.kagenti-system.svc:8000` | +| `rossoctl_api_url` | `rossoctl-api.localtest.me:8080` | `rossoctl-api-rossoctl-system.` | `rossoctl-backend.rossoctl-system.svc:8000` | | `keycloak_api_url` | `keycloak.localtest.me:8080` | `keycloak-keycloak.` | `keycloak-service.keycloak.svc:8080` | | `tool_http_url` | `..localtest.me:8080` | `-.` | `-mcp..svc:8000` | | `agent_http_url` | `..localtest.me:8080` | `-.` | `..svc:8080` | -| `otel_collector_url` | `localhost:4327` (port-fwd) | `localhost:4327` (port-fwd) | `otel-collector.kagenti-system.svc:8335` | +| `otel_collector_url` | `localhost:4327` (port-fwd) | `localhost:4327` (port-fwd) | `otel-collector.rossoctl-system.svc:8335` | | `prometheus_url` | `localhost:9191` (port-fwd) | `localhost:9191` (port-fwd) | `prometheus.istio-system.svc:9090` | If `CLUSTER_MODE` is unset, `urls.sh` infers it: `KUBERNETES_SERVICE_HOST` ⇒ diff --git a/exgentic_a2a_runner/evaluate-benchmark.sh b/exgentic_a2a_runner/evaluate-benchmark.sh index 1ee6fb3..1725659 100755 --- a/exgentic_a2a_runner/evaluate-benchmark.sh +++ b/exgentic_a2a_runner/evaluate-benchmark.sh @@ -12,7 +12,7 @@ BENCHMARK_NAME="" AGENT_NAME="" EXPERIMENT_NAME="default" MLFLOW_ENABLED="true" -OTEL_COLLECTOR_NAMESPACE="kagenti-system" +OTEL_COLLECTOR_NAMESPACE="rossoctl-system" OTEL_COLLECTOR_SERVICE="otel-collector" OTEL_COLLECTOR_LOCAL_PORT="${OTEL_COLLECTOR_LOCAL_PORT:-4327}" CLUSTER_MODE="" diff --git a/exgentic_a2a_runner/exgentic_a2a_runner/__init__.py b/exgentic_a2a_runner/exgentic_a2a_runner/__init__.py index 5916f88..ff346f7 100644 --- a/exgentic_a2a_runner/exgentic_a2a_runner/__init__.py +++ b/exgentic_a2a_runner/exgentic_a2a_runner/__init__.py @@ -1,7 +1,7 @@ -"""Exgentic A2A Runner - Benchmark harness for Kagenti agents. +"""Exgentic A2A Runner - Benchmark harness for Rossoctl agents. This package provides a test harness that integrates Exgentic benchmarks -with Kagenti agents using the A2A protocol. +with Rossoctl agents using the A2A protocol. """ __version__ = "0.1.0" diff --git a/exgentic_a2a_runner/k8s/job.yaml b/exgentic_a2a_runner/k8s/job.yaml index 70438bd..2b86f5b 100644 --- a/exgentic_a2a_runner/k8s/job.yaml +++ b/exgentic_a2a_runner/k8s/job.yaml @@ -10,7 +10,7 @@ spec: spec: restartPolicy: Never # Uses the default ServiceAccount — no kubectl / RBAC required. - # All cluster interaction goes through the Kagenti API and Keycloak over HTTP. + # All cluster interaction goes through the Rossoctl API and Keycloak over HTTP. containers: - name: runner image: ghcr.io/exgentic/runner:latest @@ -26,7 +26,7 @@ spec: - name: KEYCLOAK_PASSWORD valueFrom: secretKeyRef: - name: kagenti-test-user + name: rossoctl-test-user key: password - name: OPENAI_API_KEY valueFrom: diff --git a/exgentic_a2a_runner/libsh/check-kubectl-context.sh b/exgentic_a2a_runner/libsh/check-kubectl-context.sh index 4d4d34a..1f425b7 100644 --- a/exgentic_a2a_runner/libsh/check-kubectl-context.sh +++ b/exgentic_a2a_runner/libsh/check-kubectl-context.sh @@ -2,7 +2,7 @@ # Verify kubectl is available and points to the expected cluster for CLUSTER_MODE. # Must be sourced after CLUSTER_MODE and KUBECTL_BIN are set. # -# kind → context must be "kind-kagenti" +# kind → context must be "kind-rossoctl" # openshift → context must expose apps.openshift.io API groups # in-cluster → no check (kubectl is not available inside the Job pod) @@ -35,8 +35,8 @@ check_kubectl_context() { case "$CLUSTER_MODE" in kind) - if [ "$CURRENT_CONTEXT" != "kind-kagenti" ]; then - echo "Error: --kind requires kubectl context 'kind-kagenti', but current context is '$CURRENT_CONTEXT'" + if [ "$CURRENT_CONTEXT" != "kind-rossoctl" ]; then + echo "Error: --kind requires kubectl context 'kind-rossoctl', but current context is '$CURRENT_CONTEXT'" exit 1 fi echo "Kind cluster verified (context: $CURRENT_CONTEXT)" diff --git a/exgentic_a2a_runner/libsh/urls.sh b/exgentic_a2a_runner/libsh/urls.sh index d7e242c..1bde165 100755 --- a/exgentic_a2a_runner/libsh/urls.sh +++ b/exgentic_a2a_runner/libsh/urls.sh @@ -27,12 +27,12 @@ _urls_unsupported_mode() { exit 1 } -kagenti_api_url() { +rossoctl_api_url() { case "$CLUSTER_MODE" in - kind) echo "http://kagenti-api.localtest.me:8080" ;; - openshift) echo "https://kagenti-api-kagenti-system.${INGRESS_DOMAIN}" ;; - in-cluster) echo "http://kagenti-backend.kagenti-system.svc.cluster.local:8000" ;; - *) _urls_unsupported_mode "kagenti_api_url" ;; + kind) echo "http://rossoctl-api.localtest.me:8080" ;; + openshift) echo "https://rossoctl-api-rossoctl-system.${INGRESS_DOMAIN}" ;; + in-cluster) echo "http://rossoctl-backend.rossoctl-system.svc.cluster.local:8000" ;; + *) _urls_unsupported_mode "rossoctl_api_url" ;; esac } @@ -95,7 +95,7 @@ otel_collector_url() { # Port 8335 is the HTTP/protobuf OTLP port the collector actually binds. # 4317 is gRPC-only; curl-based health checks and http/protobuf exporters # must use 8335. - echo "http://otel-collector.kagenti-system.svc.cluster.local:8335" ;; + echo "http://otel-collector.rossoctl-system.svc.cluster.local:8335" ;; *) _urls_unsupported_mode "otel_collector_url" ;; esac } diff --git a/exgentic_a2a_runner/pyproject.toml b/exgentic_a2a_runner/pyproject.toml index a6596c2..003520a 100644 --- a/exgentic_a2a_runner/pyproject.toml +++ b/exgentic_a2a_runner/pyproject.toml @@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta" [project] name = "exgentic-a2a-runner" version = "0.1.0" -description = "Exgentic Benchmark A2A Runner for Kagenti" +description = "Exgentic Benchmark A2A Runner for Rossoctl" readme = "README.md" requires-python = ">=3.11" dependencies = [ diff --git a/exgentic_a2a_runner/sync-image-to-cluster.sh b/exgentic_a2a_runner/sync-image-to-cluster.sh index a08c881..b3e682e 100755 --- a/exgentic_a2a_runner/sync-image-to-cluster.sh +++ b/exgentic_a2a_runner/sync-image-to-cluster.sh @@ -6,14 +6,14 @@ # REMOTE_IMAGE_NAME - the full image reference (e.g. ghcr.io/exgentic/foo:latest) # # Optional env vars: -# KIND_CLUSTER_NAME - name of the kind cluster (default: kagenti) +# KIND_CLUSTER_NAME - name of the kind cluster (default: rossoctl) # # Exports on success: # IMAGE_NAME - set to REMOTE_IMAGE_NAME (for callers) set -e -KIND_CLUSTER_NAME="${KIND_CLUSTER_NAME:-kagenti}" +KIND_CLUSTER_NAME="${KIND_CLUSTER_NAME:-rossoctl}" if [ -z "$REMOTE_IMAGE_NAME" ]; then echo "Error: REMOTE_IMAGE_NAME is not set" From a5284382f7f57e968de140c262a16907f4d0cdd7 Mon Sep 17 00:00:00 2001 From: Yoav Katz Date: Thu, 23 Jul 2026 18:00:27 +0300 Subject: [PATCH 2/2] Removed OTL collector code, which belongs in a different PR Signed-off-by: Yoav Katz --- .../authbridge/pipeline-merge.py | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/exgentic_a2a_runner/authbridge/pipeline-merge.py b/exgentic_a2a_runner/authbridge/pipeline-merge.py index ebfdc56..a0e7d3b 100755 --- a/exgentic_a2a_runner/authbridge/pipeline-merge.py +++ b/exgentic_a2a_runner/authbridge/pipeline-merge.py @@ -236,23 +236,6 @@ def main() -> int: pipeline.setdefault("inbound", {})["plugins"] = inbound_entries pipeline.setdefault("outbound", {})["plugins"] = outbound_entries - # Ensure the OTEL collector bypasses the authbridge listener. Without this - # the proxy intercepts OTLP egress and resets the connection, which the - # exgentic library misreports as "Protocol mismatch" causing a crash-loop - # (issue #34). We add both the FQDN and the short name in case the exporter - # ever resolves via the short form. - otel_skip = [ - "otel-collector.rossoctl-system.svc.cluster.local", - "otel-collector", - ] - listener = operator.setdefault("listener", {}) - existing = listener.get("skip_hosts") or [] - merged_skip = list(existing) - for host in otel_skip: - if host not in merged_skip: - merged_skip.append(host) - listener["skip_hosts"] = merged_skip - sys.stdout.write( yaml.safe_dump(operator, default_flow_style=False, sort_keys=False) )