From 58311ac25d1b766d2053240259f7e6859a620a1e Mon Sep 17 00:00:00 2001 From: sagarikapandey17 Date: Wed, 27 May 2026 12:16:09 -0700 Subject: [PATCH 1/2] Add Windows PowerShell scripts for cloud-deployment example (#395) Add deploy.ps1, cleanup.ps1, and verify.ps1 as Windows equivalents of the existing bash scripts. Fixes #395. - deploy.ps1: full cluster setup (Kind, registry, Strimzi, PostgreSQL, Kafka, agent) with -ContainerTool docker|podman parameter - cleanup.ps1: reverse-order teardown with confirmation prompt - verify.ps1: health checks for all deployed components Key translation notes: - Bash heredocs -> PowerShell here-strings piped to kubectl/docker stdin - export VAR=val -> $env:VAR = 'val' - grep/|| true -> -match / $LASTEXITCODE checks - sleep N -> Start-Sleep -Seconds N - curl -> curl.exe (avoids PowerShell Invoke-WebRequest alias) - SKIP_ENTITY_OPERATOR_WAIT and SKIP_AGENT_DEPLOY env vars supported Also updates README.md with Windows quick-start instructions, PowerShell execution policy note, and updated project structure table. --- examples/cloud-deployment/README.md | 61 ++- examples/cloud-deployment/scripts/cleanup.ps1 | 78 ++++ examples/cloud-deployment/scripts/deploy.ps1 | 356 ++++++++++++++++++ examples/cloud-deployment/scripts/verify.ps1 | 100 +++++ 4 files changed, 589 insertions(+), 6 deletions(-) create mode 100644 examples/cloud-deployment/scripts/cleanup.ps1 create mode 100644 examples/cloud-deployment/scripts/deploy.ps1 create mode 100644 examples/cloud-deployment/scripts/verify.ps1 diff --git a/examples/cloud-deployment/README.md b/examples/cloud-deployment/README.md index 3028f0e29..a81c400a2 100644 --- a/examples/cloud-deployment/README.md +++ b/examples/cloud-deployment/README.md @@ -78,7 +78,9 @@ See https://kubernetes.io/docs/tasks/tools/ for installation instructions. ### 2. Deploy the Stack -The deployment script will automatically create the Kind cluster and deploy all components: +The deployment script will automatically create the Kind cluster and deploy all components. + +#### macOS / Linux ```bash cd scripts @@ -90,9 +92,40 @@ cd scripts ./deploy.sh --container-tool podman ``` +#### Windows + +PowerShell scripts are provided as the Windows equivalent of the bash scripts. +Open **PowerShell** (Windows Terminal recommended) and run: + +```powershell +cd scripts + +# Allow the script to run in this session (one-time, current session only) +Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass + +.\deploy.ps1 +``` + +**If using Podman instead of Docker:** +```powershell +.\deploy.ps1 -ContainerTool podman +``` + +**Troubleshooting entity operator timeout on Windows:** + +If Kafka deployment times out waiting for the entity operator, set the environment variable and retry: + +```powershell +.\cleanup.ps1 +$env:SKIP_ENTITY_OPERATOR_WAIT = "true" +.\deploy.ps1 +``` + +--- + Note that using Kind with Podman on Linux may have some occasional issues due to Kind's experimental support for Podman. In our testing, a reboot normally solves this. -**Troubleshooting entity operator timeout:** +**Troubleshooting entity operator timeout (macOS / Linux):** In some environments (particularly Linux with Podman), the Kafka entity operator may not start properly, causing deployment to timeout while waiting for Kafka to be ready. If you encounter this issue, you can skip the entity operator wait: @@ -119,10 +152,16 @@ The script will: ### 3. Verify Deployment +**macOS / Linux:** ```bash ./verify.sh ``` +**Windows:** +```powershell +.\verify.ps1 +``` + Expected output: ``` ✓ Namespace 'a2a-demo' exists @@ -470,11 +509,18 @@ docker system prune -a # or: podman system prune -a To remove all deployed resources: +**macOS / Linux:** ```bash cd scripts ./cleanup.sh ``` +**Windows:** +```powershell +cd scripts +.\cleanup.ps1 +``` + This will delete: - A2A agent deployment and service - Kafka cluster @@ -508,7 +554,7 @@ podman stop kind-registry && podman rm kind-registry docker system prune -a # or: podman system prune -a ``` -Then re-run `./deploy.sh` to start fresh. +Then re-run `./deploy.sh` (macOS/Linux) or `.\deploy.ps1` (Windows) to start fresh. ## Project Structure @@ -534,9 +580,12 @@ cloud-deployment/ ├── strimzi-1.0.0/ │ └── strimzi-cluster-operator-1.0.0.yaml # Pinned from https://strimzi.io/install/latest?namespace=kafka ├── scripts/ -│ ├── deploy.sh # Automated deployment -│ ├── verify.sh # Health checks -│ └── cleanup.sh # Resource cleanup +│ ├── deploy.sh # Automated deployment (macOS/Linux) +│ ├── deploy.ps1 # Automated deployment (Windows) +│ ├── verify.sh # Health checks (macOS/Linux) +│ ├── verify.ps1 # Health checks (Windows) +│ ├── cleanup.sh # Resource cleanup (macOS/Linux) +│ └── cleanup.ps1 # Resource cleanup (Windows) └── README.md # This file ``` diff --git a/examples/cloud-deployment/scripts/cleanup.ps1 b/examples/cloud-deployment/scripts/cleanup.ps1 new file mode 100644 index 000000000..de941661b --- /dev/null +++ b/examples/cloud-deployment/scripts/cleanup.ps1 @@ -0,0 +1,78 @@ +<# +.SYNOPSIS + Tear down the A2A Cloud example Kubernetes deployment. +.DESCRIPTION + Deletes all deployed resources in reverse order, removes the Kind cluster + and local registry container. Windows equivalent of cleanup.sh. +.PARAMETER ContainerTool + Container runtime to use: 'docker' (default) or 'podman'. +.EXAMPLE + .\cleanup.ps1 + .\cleanup.ps1 -ContainerTool podman +.NOTES + Requires PowerShell 5.1 or later. Run with: + Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass + before running this script if your system policy blocks unsigned scripts. +#> +param( + [ValidateSet("docker", "podman")] + [string]$ContainerTool = "docker" +) + +Write-Host "============================================" +Write-Host "A2A Cloud Deployment - Cleanup Script" +Write-Host "============================================" +Write-Host "" + +# Configure Kind to use podman if specified +if ($ContainerTool -eq "podman") { + $env:KIND_EXPERIMENTAL_PROVIDER = "podman" +} + +Write-Host "This will delete all resources in the a2a-demo namespace and the Kind cluster" -ForegroundColor Yellow +$reply = Read-Host "Are you sure you want to continue? (y/N)" + +if ($reply -notmatch "^[Yy]$") { + Write-Host "Cleanup cancelled" + exit 0 +} + +Write-Host "" +Write-Host "Deleting A2A Agent..." +kubectl delete -f "..\k8s\05-agent-deployment.yaml" --ignore-not-found=true + +Write-Host "" +Write-Host "Deleting ConfigMap..." +kubectl delete -f "..\k8s\04-agent-configmap.yaml" --ignore-not-found=true + +Write-Host "" +Write-Host "Deleting Kafka topic..." +kubectl delete -f "..\k8s\03-kafka-topic.yaml" --ignore-not-found=true + +Write-Host "" +Write-Host "Deleting Kafka..." +kubectl delete -f "..\k8s\02-kafka.yaml" --ignore-not-found=true + +Write-Host "" +Write-Host "Deleting PostgreSQL..." +kubectl delete -f "..\k8s\01-postgres.yaml" --ignore-not-found=true + +Write-Host "" +Write-Host "Deleting namespace..." +kubectl delete -f "..\k8s\00-namespace.yaml" --ignore-not-found=true + +Write-Host "" +Write-Host "Deleting Kind cluster..." +kind delete cluster + +Write-Host "" +Write-Host "Stopping and removing registry container..." +$null = & $ContainerTool stop kind-registry 2>$null +$null = & $ContainerTool rm kind-registry 2>$null + +Write-Host "" +Write-Host "Cleanup completed" -ForegroundColor Green +Write-Host "" +Write-Host "Note: Strimzi operator was not removed" -ForegroundColor Yellow +Write-Host "To remove Strimzi operator, run:" +Write-Host " kubectl delete namespace kafka" diff --git a/examples/cloud-deployment/scripts/deploy.ps1 b/examples/cloud-deployment/scripts/deploy.ps1 new file mode 100644 index 000000000..82ab8a589 --- /dev/null +++ b/examples/cloud-deployment/scripts/deploy.ps1 @@ -0,0 +1,356 @@ +<# +.SYNOPSIS + Deploy the A2A Cloud example to a local Kubernetes cluster (Kind). +.DESCRIPTION + Sets up a local Kind cluster with a container registry, PostgreSQL, Kafka (via Strimzi), + and deploys the A2A agent. Windows equivalent of deploy.sh. +.PARAMETER ContainerTool + Container runtime to use: 'docker' (default) or 'podman'. +.EXAMPLE + .\deploy.ps1 + .\deploy.ps1 -ContainerTool podman +.NOTES + Requires PowerShell 5.1 or later. Run with: + Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass + before running this script if your system policy blocks unsigned scripts. +#> +param( + [ValidateSet("docker", "podman")] + [string]$ContainerTool = "docker" +) + +Write-Host "=========================================" +Write-Host "A2A Cloud Deployment - Deployment Script" +Write-Host "=========================================" +Write-Host "" + +Write-Host "Container tool: $ContainerTool" +Write-Host "" + +# Configure Kind to use podman if specified +if ($ContainerTool -eq "podman") { + $env:KIND_EXPERIMENTAL_PROVIDER = "podman" + Write-Host "Configured Kind to use podman provider" + Write-Host "" +} + +# Check if Kind is installed +if (-not (Get-Command kind -ErrorAction SilentlyContinue)) { + Write-Host "Error: Kind is not installed" -ForegroundColor Red + Write-Host "Please install Kind first: https://kind.sigs.k8s.io/docs/user/quick-start/#installation" + exit 1 +} + +# Check if kubectl is installed +if (-not (Get-Command kubectl -ErrorAction SilentlyContinue)) { + Write-Host "Error: kubectl is not installed" -ForegroundColor Red + Write-Host "Please install kubectl first: https://kubernetes.io/docs/tasks/tools/" + exit 1 +} + +# Setup local registry +Write-Host "Setting up local registry..." +$RegName = "kind-registry" +$RegPort = "5001" + +# Create registry container if it doesn't exist +$running = & $ContainerTool inspect -f '{{.State.Running}}' $RegName 2>$null +if ($running -ne "true") { + Write-Host "Creating registry container..." + & $ContainerTool run ` + -d --restart=always -p "127.0.0.1:${RegPort}:5000" --network bridge --name $RegName ` + mirror.gcr.io/library/registry:2 + Write-Host "✓ Registry container created" -ForegroundColor Green +} else { + Write-Host "✓ Registry container already running" -ForegroundColor Green +} + +# Create Kind cluster if it doesn't exist +Write-Host "" +$clusters = kind get clusters 2>$null +if ($clusters -notmatch "(?m)^kind$") { + Write-Host "Creating Kind cluster..." + kind create cluster --config="..\kind-config.yaml" + Write-Host "✓ Kind cluster created" -ForegroundColor Green +} else { + # Check if cluster is healthy by trying to get nodes + $null = kubectl get nodes 2>$null + if ($LASTEXITCODE -ne 0) { + Write-Host "Error: Existing Kind cluster is not healthy" -ForegroundColor Red + Write-Host "" + Write-Host "The cluster exists but is not responding. This usually means:" + Write-Host " - The cluster containers are stopped" + Write-Host " - The cluster is in a corrupted state" + Write-Host "" + Write-Host "To fix this, delete the cluster and re-run this script:" + Write-Host " kind delete cluster" + Write-Host " .\deploy.ps1" + Write-Host "" + exit 1 + } else { + Write-Host "✓ Kind cluster already exists and is healthy" -ForegroundColor Green + } +} + +# Configure registry on cluster nodes +Write-Host "" +Write-Host "Configuring registry on cluster nodes..." +$RegistryDir = "/etc/containerd/certs.d/localhost:${RegPort}" +foreach ($node in (kind get nodes)) { + & $ContainerTool exec $node mkdir -p $RegistryDir + "[host.`"http://${RegName}:5000`"]" | & $ContainerTool exec -i $node sh -c "cat > ${RegistryDir}/hosts.toml" +} +Write-Host "✓ Registry configured on nodes" -ForegroundColor Green + +# Connect registry to cluster network +Write-Host "" +Write-Host "Connecting registry to cluster network..." +$networkInfo = & $ContainerTool inspect -f '{{json .NetworkSettings.Networks.kind}}' $RegName 2>$null +if ($networkInfo -eq "null" -or [string]::IsNullOrEmpty($networkInfo)) { + & $ContainerTool network connect "kind" $RegName + Write-Host "✓ Registry connected to cluster network" -ForegroundColor Green +} else { + Write-Host "✓ Registry already connected" -ForegroundColor Green +} + +# Create ConfigMap to document local registry +Write-Host "" +Write-Host "Creating registry ConfigMap..." +@" +apiVersion: v1 +kind: ConfigMap +metadata: + name: local-registry-hosting + namespace: kube-public +data: + localRegistryHosting.v1: | + host: "localhost:${RegPort}" + help: "https://kind.sigs.k8s.io/docs/user/local-registry/" +"@ | kubectl apply -f - +Write-Host "✓ Registry ConfigMap created" -ForegroundColor Green + +# Verify registry is accessible +Write-Host "" +Write-Host "Verifying registry is accessible..." +$null = curl.exe -s "http://localhost:${RegPort}/v2/" 2>$null +if ($LASTEXITCODE -eq 0) { + Write-Host "✓ Registry accessible at localhost:${RegPort}" -ForegroundColor Green +} else { + Write-Host "ERROR: Registry not accessible" -ForegroundColor Red + exit 1 +} + +# Build the project and container image from the server directory +Write-Host "" +Write-Host "Building the project..." +Push-Location "..\server" +try { + mvn clean package -DskipTests + if ($LASTEXITCODE -ne 0) { + Write-Host "ERROR: Maven build failed" -ForegroundColor Red + exit 1 + } + Write-Host "✓ Project built successfully" -ForegroundColor Green + + # Build and push container image to local registry + $Registry = "localhost:${RegPort}" + Write-Host "" + Write-Host "Building container image..." + & $ContainerTool build -t "${Registry}/a2a-cloud-deployment:latest" . + if ($LASTEXITCODE -ne 0) { + Write-Host "ERROR: Container image build failed" -ForegroundColor Red + exit 1 + } + Write-Host "✓ Container image built" -ForegroundColor Green + + Write-Host "Pushing image to local registry..." + if ($ContainerTool -eq "podman") { + & $ContainerTool push --tls-verify=false "${Registry}/a2a-cloud-deployment:latest" + } else { + & $ContainerTool push "${Registry}/a2a-cloud-deployment:latest" + } + if ($LASTEXITCODE -ne 0) { + Write-Host "ERROR: Image push failed" -ForegroundColor Red + exit 1 + } + Write-Host "✓ Image pushed to registry" -ForegroundColor Green +} finally { + Pop-Location +} + +# Install Strimzi operator if not already installed +Write-Host "" +Write-Host "Checking for Strimzi operator..." + +# Ensure kafka namespace exists +$null = kubectl get namespace kafka 2>$null +if ($LASTEXITCODE -ne 0) { + Write-Host "Creating kafka namespace..." + kubectl create namespace kafka +} + +$null = kubectl get crd kafkas.kafka.strimzi.io 2>$null +if ($LASTEXITCODE -ne 0) { + Write-Host "Installing Strimzi operator..." + kubectl create -f 'https://strimzi.io/install/latest?namespace=kafka' -n kafka + + Write-Host "Waiting for Strimzi operator deployment to be created..." + for ($i = 1; $i -le 30; $i++) { + $null = kubectl get deployment strimzi-cluster-operator -n kafka 2>$null + if ($LASTEXITCODE -eq 0) { + Write-Host "Deployment found" + break + } + if ($i -eq 30) { + Write-Host "ERROR: Deployment not found after 30 seconds" -ForegroundColor Red + exit 1 + } + Start-Sleep -Seconds 1 + } + + Write-Host "Waiting for Strimzi operator to be ready..." + kubectl wait --for=condition=Available deployment/strimzi-cluster-operator -n kafka --timeout=300s + kubectl wait --for=condition=Ready pod -l name=strimzi-cluster-operator -n kafka --timeout=300s + Write-Host "✓ Strimzi operator installed" -ForegroundColor Green +} else { + Write-Host "✓ Strimzi operator already installed" -ForegroundColor Green +} + +# Create namespace +Write-Host "" +Write-Host "Creating namespace..." +kubectl apply -f "..\k8s\00-namespace.yaml" +Write-Host "✓ Namespace created" -ForegroundColor Green + +# Deploy PostgreSQL +Write-Host "" +Write-Host "Deploying PostgreSQL..." +kubectl apply -f "..\k8s\01-postgres.yaml" +Write-Host "Waiting for PostgreSQL to be ready..." +kubectl wait --for=condition=Ready pod -l app=postgres -n a2a-demo --timeout=120s +Write-Host "✓ PostgreSQL deployed" -ForegroundColor Green + +# Deploy Kafka +Write-Host "" +Write-Host "Deploying Kafka..." +kubectl apply -f "..\k8s\02-kafka.yaml" +Write-Host "Waiting for Kafka to be ready (using KRaft mode, typically 2-3 minutes. Timeout is 10 minutes)..." + +if ($env:SKIP_ENTITY_OPERATOR_WAIT -eq "true") { + Write-Host "⚠ SKIP_ENTITY_OPERATOR_WAIT is set - checking broker pod only" -ForegroundColor Yellow + + for ($i = 1; $i -le 60; $i++) { + Write-Host "Checking Kafka broker status (attempt $i/60)..." + kubectl get pods -n kafka -l strimzi.io/cluster=a2a-kafka 2>$null + + $null = kubectl wait --for=condition=Ready pod/a2a-kafka-broker-0 -n kafka --timeout=5s 2>$null + if ($LASTEXITCODE -eq 0) { + Write-Host "✓ Kafka broker pod is ready" -ForegroundColor Green + Write-Host "⚠ Entity operator may not be ready, but this does not affect functionality" -ForegroundColor Yellow + break + } + + if ($i -eq 60) { + Write-Host "ERROR: Timeout waiting for Kafka broker" -ForegroundColor Red + kubectl get pods -n kafka -l strimzi.io/cluster=a2a-kafka + kubectl describe pod a2a-kafka-broker-0 -n kafka 2>$null + exit 1 + } + + Start-Sleep -Seconds 5 + } +} else { + Write-Host "⚠ If waiting for Kafka times out, run .\cleanup.ps1 and retry with: `$env:SKIP_ENTITY_OPERATOR_WAIT = 'true'" -ForegroundColor Yellow + + for ($i = 1; $i -le 60; $i++) { + Write-Host "Checking Kafka status (attempt $i/60)..." + kubectl get kafka -n kafka -o wide 2>$null + kubectl get pods -n kafka -l strimzi.io/cluster=a2a-kafka 2>$null + + $null = kubectl wait --for=condition=Ready kafka/a2a-kafka -n kafka --timeout=10s 2>$null + if ($LASTEXITCODE -eq 0) { + Write-Host "✓ Kafka deployed" -ForegroundColor Green + break + } + + if ($i -eq 60) { + Write-Host "ERROR: Timeout waiting for Kafka" -ForegroundColor Red + kubectl describe kafka/a2a-kafka -n kafka + kubectl get events -n kafka --sort-by='.lastTimestamp' + exit 1 + } + } +} + +# Create Kafka Topic for event replication +Write-Host "" +Write-Host "Creating Kafka topic for event replication..." +kubectl apply -f "..\k8s\03-kafka-topic.yaml" + +if ($env:SKIP_ENTITY_OPERATOR_WAIT -eq "true") { + Write-Host "⚠ SKIP_ENTITY_OPERATOR_WAIT is set - polling Kafka broker for topic" -ForegroundColor Yellow + Write-Host " Topic operator may not be ready, waiting for broker to create topic. This check can take several minutes..." + + for ($i = 1; $i -le 30; $i++) { + $topics = kubectl exec a2a-kafka-broker-0 -n kafka -- /opt/kafka/bin/kafka-topics.sh --list --bootstrap-server localhost:9092 2>$null + if ($topics -match "a2a-replicated-events") { + Write-Host "✓ Topic exists in Kafka broker" -ForegroundColor Green + break + } + if ($i -eq 30) { + Write-Host "ERROR: Topic not found in broker after 30 attempts" -ForegroundColor Red + exit 1 + } + Start-Sleep -Seconds 2 + } +} else { + Write-Host "Waiting for Kafka topic to be ready..." + kubectl wait --for=condition=Ready kafkatopic/a2a-replicated-events -n kafka --timeout=60s + if ($LASTEXITCODE -eq 0) { + Write-Host "✓ Kafka topic created" -ForegroundColor Green + } else { + Write-Host "ERROR: Timeout waiting for Kafka topic" -ForegroundColor Red + Write-Host "⚠ The topic operator may not be ready in this environment." -ForegroundColor Yellow + Write-Host "⚠ Run .\cleanup.ps1, then retry with: `$env:SKIP_ENTITY_OPERATOR_WAIT = 'true'" -ForegroundColor Yellow + exit 1 + } +} + +# Deploy Agent ConfigMap +Write-Host "" +Write-Host "Deploying Agent ConfigMap..." +kubectl apply -f "..\k8s\04-agent-configmap.yaml" +Write-Host "✓ ConfigMap deployed" -ForegroundColor Green + +# Deploy Agent +if ($env:SKIP_AGENT_DEPLOY -ne "true") { + Write-Host "" + Write-Host "Deploying A2A Agent..." + kubectl apply -f "..\k8s\05-agent-deployment.yaml" + + Write-Host "Waiting for Agent pods to be ready..." + kubectl wait --for=condition=Ready pod -l app=a2a-agent -n a2a-demo --timeout=120s + Write-Host "✓ Agent deployed" -ForegroundColor Green +} else { + Write-Host "" + Write-Host "⚠ Skipping agent deployment (SKIP_AGENT_DEPLOY=true)" -ForegroundColor Yellow + Write-Host " ConfigMap has been deployed, you can manually deploy the agent with:" + Write-Host " kubectl apply -f ..\k8s\05-agent-deployment.yaml" +} + +Write-Host "" +Write-Host "=========================================" -ForegroundColor Green +Write-Host "Deployment completed successfully!" -ForegroundColor Green +Write-Host "=========================================" -ForegroundColor Green +Write-Host "" +Write-Host "To verify the deployment, run:" +Write-Host " .\verify.ps1" +Write-Host "" +Write-Host "To access the agent (via NodePort):" +Write-Host " curl.exe http://localhost:8080/.well-known/agent-card.json" +Write-Host "" +Write-Host "To run the test client (demonstrating load balancing):" +Write-Host " cd ..\server" +Write-Host " mvn test-compile exec:java -Dexec.classpathScope=test ``" +Write-Host " -Dexec.mainClass=`"io.a2a.examples.cloud.A2ACloudExampleClient`" ``" +Write-Host " -Dagent.url=`"http://localhost:8080`"" diff --git a/examples/cloud-deployment/scripts/verify.ps1 b/examples/cloud-deployment/scripts/verify.ps1 new file mode 100644 index 000000000..badf21709 --- /dev/null +++ b/examples/cloud-deployment/scripts/verify.ps1 @@ -0,0 +1,100 @@ +<# +.SYNOPSIS + Verify the A2A Cloud example deployment. +.DESCRIPTION + Checks that all deployed components (namespace, PostgreSQL, Kafka, agent pods, + and agent service) are healthy. Windows equivalent of verify.sh. +.EXAMPLE + .\verify.ps1 +.NOTES + Requires PowerShell 5.1 or later. Run with: + Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass + before running this script if your system policy blocks unsigned scripts. +#> + +Write-Host "============================================" +Write-Host "A2A Cloud Deployment - Verification Script" +Write-Host "============================================" +Write-Host "" + +# Check namespace exists +Write-Host "Checking namespace..." +$null = kubectl get namespace a2a-demo 2>$null +if ($LASTEXITCODE -eq 0) { + Write-Host "✓ Namespace 'a2a-demo' exists" -ForegroundColor Green +} else { + Write-Host "✗ Namespace 'a2a-demo' not found" -ForegroundColor Red + exit 1 +} + +# Check PostgreSQL +Write-Host "" +Write-Host "Checking PostgreSQL..." +$postgresReady = kubectl get pods -n a2a-demo -l app=postgres ` + -o "jsonpath={.items[0].status.conditions[?(@.type=='Ready')].status}" 2>$null +if ($postgresReady -eq "True") { + Write-Host "✓ PostgreSQL is ready" -ForegroundColor Green + kubectl get pods -n a2a-demo -l app=postgres +} else { + Write-Host "✗ PostgreSQL is not ready (Ready: $postgresReady)" -ForegroundColor Red + kubectl get pods -n a2a-demo -l app=postgres +} + +# Check Kafka +Write-Host "" +Write-Host "Checking Kafka..." +$kafkaReady = kubectl get kafka a2a-kafka -n kafka ` + -o "jsonpath={.status.conditions[?(@.type=='Ready')].status}" 2>$null +if ($kafkaReady -eq "True") { + Write-Host "✓ Kafka is ready" -ForegroundColor Green + kubectl get kafka -n kafka +} else { + Write-Host "⚠ Kafka may not be fully ready (Status: $kafkaReady)" -ForegroundColor Yellow + kubectl get kafka -n kafka +} + +# Check Agent pods +Write-Host "" +Write-Host "Checking A2A Agent pods..." +$agentStatusJson = kubectl get pods -n a2a-demo -l app=a2a-agent ` + -o "jsonpath={range .items[*]}{.status.conditions[?(@.type=='Ready')].status}{'\n'}{end}" 2>$null +$agentReady = ($agentStatusJson -split "`n" | Where-Object { $_ -eq "True" }).Count +$agentTotal = (kubectl get pods -n a2a-demo -l app=a2a-agent ` + -o "jsonpath={range .items[*]}{.metadata.name}{'\n'}{end}" 2>$null ` + | Where-Object { $_ -ne "" }).Count + +Write-Host "Total pods: $agentTotal" +Write-Host "Ready pods: $agentReady" + +if ($agentReady -ge 2) { + Write-Host "✓ Agent pods are running" -ForegroundColor Green + kubectl get pods -n a2a-demo -l app=a2a-agent -o wide +} else { + Write-Host "⚠ Not all agent pods are ready" -ForegroundColor Yellow + kubectl get pods -n a2a-demo -l app=a2a-agent -o wide +} + +# Check Agent service +Write-Host "" +Write-Host "Checking A2A Agent service..." +$null = kubectl get svc a2a-agent-service -n a2a-demo 2>$null +if ($LASTEXITCODE -eq 0) { + Write-Host "✓ Agent service exists" -ForegroundColor Green + kubectl get svc a2a-agent-service -n a2a-demo +} else { + Write-Host "✗ Agent service not found" -ForegroundColor Red +} + +# Instructions +Write-Host "" +Write-Host "==========================================" +Write-Host "To test the agent (via NodePort):" +Write-Host "" +Write-Host " curl.exe http://localhost:8080/.well-known/agent-card.json" +Write-Host "" +Write-Host "To run the test client (demonstrating load balancing):" +Write-Host " cd ..\server" +Write-Host " mvn test-compile exec:java -Dexec.classpathScope=test ``" +Write-Host " -Dexec.mainClass=`"io.a2a.examples.cloud.A2ACloudExampleClient`" ``" +Write-Host " -Dagent.url=`"http://localhost:8080`"" +Write-Host "==========================================" From 8f7a04f66e1df0a8b46c430420397e17d73ba747 Mon Sep 17 00:00:00 2001 From: sagarikapandey17 Date: Wed, 27 May 2026 12:44:23 -0700 Subject: [PATCH 2/2] fix: address Gemini Code Assist review comments - Add missing dependency checks for Maven and container tool - Trim docker/podman inspect output to handle CRLF on Windows - Use \r? in kind cluster regex to match Windows line endings - Use -match '^True\s*$' instead of -eq 'True' in verify.ps1 to handle trailing whitespace/carriage returns in kubectl output --- examples/cloud-deployment/scripts/deploy.ps1 | 22 +++++++++++++++++--- examples/cloud-deployment/scripts/verify.ps1 | 8 ++++--- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/examples/cloud-deployment/scripts/deploy.ps1 b/examples/cloud-deployment/scripts/deploy.ps1 index 82ab8a589..ea2f5208a 100644 --- a/examples/cloud-deployment/scripts/deploy.ps1 +++ b/examples/cloud-deployment/scripts/deploy.ps1 @@ -48,13 +48,27 @@ if (-not (Get-Command kubectl -ErrorAction SilentlyContinue)) { exit 1 } +# Check if Maven is installed +if (-not (Get-Command mvn -ErrorAction SilentlyContinue)) { + Write-Host "Error: Maven (mvn) is not installed" -ForegroundColor Red + Write-Host "Please install Maven first: https://maven.apache.org/install.html" + exit 1 +} + +# Check if the container tool is installed +if (-not (Get-Command $ContainerTool -ErrorAction SilentlyContinue)) { + Write-Host "Error: $ContainerTool is not installed or not in PATH" -ForegroundColor Red + exit 1 +} + # Setup local registry Write-Host "Setting up local registry..." $RegName = "kind-registry" $RegPort = "5001" # Create registry container if it doesn't exist -$running = & $ContainerTool inspect -f '{{.State.Running}}' $RegName 2>$null +# .Trim() strips trailing \r\n from docker/podman output on Windows +$running = (& $ContainerTool inspect -f '{{.State.Running}}' $RegName 2>$null).Trim() if ($running -ne "true") { Write-Host "Creating registry container..." & $ContainerTool run ` @@ -68,7 +82,8 @@ if ($running -ne "true") { # Create Kind cluster if it doesn't exist Write-Host "" $clusters = kind get clusters 2>$null -if ($clusters -notmatch "(?m)^kind$") { +# \r? handles Windows CRLF line endings in kind output +if ($clusters -notmatch "(?m)^kind\r?$") { Write-Host "Creating Kind cluster..." kind create cluster --config="..\kind-config.yaml" Write-Host "✓ Kind cluster created" -ForegroundColor Green @@ -105,7 +120,8 @@ Write-Host "✓ Registry configured on nodes" -ForegroundColor Green # Connect registry to cluster network Write-Host "" Write-Host "Connecting registry to cluster network..." -$networkInfo = & $ContainerTool inspect -f '{{json .NetworkSettings.Networks.kind}}' $RegName 2>$null +# .Trim() strips trailing \r\n from docker/podman output on Windows +$networkInfo = (& $ContainerTool inspect -f '{{json .NetworkSettings.Networks.kind}}' $RegName 2>$null).Trim() if ($networkInfo -eq "null" -or [string]::IsNullOrEmpty($networkInfo)) { & $ContainerTool network connect "kind" $RegName Write-Host "✓ Registry connected to cluster network" -ForegroundColor Green diff --git a/examples/cloud-deployment/scripts/verify.ps1 b/examples/cloud-deployment/scripts/verify.ps1 index badf21709..bb10153e7 100644 --- a/examples/cloud-deployment/scripts/verify.ps1 +++ b/examples/cloud-deployment/scripts/verify.ps1 @@ -32,7 +32,8 @@ Write-Host "" Write-Host "Checking PostgreSQL..." $postgresReady = kubectl get pods -n a2a-demo -l app=postgres ` -o "jsonpath={.items[0].status.conditions[?(@.type=='Ready')].status}" 2>$null -if ($postgresReady -eq "True") { +# -match handles trailing whitespace/CRLF in kubectl output on Windows +if ($postgresReady -match "^True\s*$") { Write-Host "✓ PostgreSQL is ready" -ForegroundColor Green kubectl get pods -n a2a-demo -l app=postgres } else { @@ -45,7 +46,7 @@ Write-Host "" Write-Host "Checking Kafka..." $kafkaReady = kubectl get kafka a2a-kafka -n kafka ` -o "jsonpath={.status.conditions[?(@.type=='Ready')].status}" 2>$null -if ($kafkaReady -eq "True") { +if ($kafkaReady -match "^True\s*$") { Write-Host "✓ Kafka is ready" -ForegroundColor Green kubectl get kafka -n kafka } else { @@ -58,7 +59,8 @@ Write-Host "" Write-Host "Checking A2A Agent pods..." $agentStatusJson = kubectl get pods -n a2a-demo -l app=a2a-agent ` -o "jsonpath={range .items[*]}{.status.conditions[?(@.type=='Ready')].status}{'\n'}{end}" 2>$null -$agentReady = ($agentStatusJson -split "`n" | Where-Object { $_ -eq "True" }).Count +# -match handles trailing \r from CRLF line endings on Windows +$agentReady = ($agentStatusJson -split "`n" | Where-Object { $_ -match "^True\s*$" }).Count $agentTotal = (kubectl get pods -n a2a-demo -l app=a2a-agent ` -o "jsonpath={range .items[*]}{.metadata.name}{'\n'}{end}" 2>$null ` | Where-Object { $_ -ne "" }).Count