Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 102 additions & 0 deletions .github/workflows/cloud-deployment-example-windows.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
name: Cloud Deployment Example Test (Windows)

on:
push:
pull_request:
workflow_dispatch:

# Only run the latest job
concurrency:
group: '${{ github.workflow }} @ ${{ github.head_ref || github.ref }}'
cancel-in-progress: true

jobs:
test-cloud-deployment-windows:
runs-on: windows-latest
timeout-minutes: 45
steps:
- name: Checkout code
uses: actions/checkout@v6

- name: Set up JDK 17
uses: actions/setup-java@v5
with:
java-version: '17'
distribution: 'temurin'
cache: maven

- name: Install Kind
shell: pwsh
run: |
curl.exe -Lo kind.exe https://kind.sigs.k8s.io/dl/v0.31.0/kind-windows-amd64.exe
Move-Item kind.exe "$env:SystemRoot\System32\kind.exe"
kind version

- name: Build project
run: mvn -B clean install -DskipTests -f pom.xml

- name: Deploy with Kind
working-directory: examples/cloud-deployment/scripts
shell: pwsh
run: .\deploy.ps1

- name: Verify deployment
working-directory: examples/cloud-deployment/scripts
shell: pwsh
run: .\verify.ps1

- name: Verify agent card is accessible
shell: pwsh
run: |
Write-Host "Testing agent card endpoint at http://localhost:8080/.well-known/agent-card.json"
curl.exe -f http://localhost:8080/.well-known/agent-card.json
if ($LASTEXITCODE -ne 0) {
Write-Host "Agent card not accessible" -ForegroundColor Red
exit 1
}

- name: Run test client
working-directory: examples/cloud-deployment/server
shell: pwsh
run: |
mvn test-compile exec:java `
-Dexec.mainClass="org.a2aproject.sdk.examples.cloud.A2ACloudExampleClient" `
-Dexec.classpathScope=test `
-Dagent.url=http://localhost:8080 `
-Dci.mode=true

- name: Show diagnostics on failure
if: failure()
shell: pwsh
run: |
Write-Host "=== Agent Pod Status ==="
kubectl get pods -n a2a-demo -l app=a2a-agent -o wide

Write-Host ""
Write-Host "=== Recent Events ==="
kubectl get events -n a2a-demo --sort-by='.lastTimestamp' | Select-Object -Last 20

Write-Host ""
Write-Host "=== Agent Pod Logs ==="
$pods = (kubectl get pods -n a2a-demo -l app=a2a-agent `
-o jsonpath='{.items[*].metadata.name}') -split ' '
foreach ($pod in $pods) {
if ($pod) {
Write-Host "--- Logs for $pod ---"
kubectl logs -n a2a-demo $pod --tail=100
}
}

Write-Host ""
Write-Host "=== PostgreSQL Logs ==="
kubectl logs -n a2a-demo postgres-0 --tail=50

Write-Host ""
Write-Host "=== Kafka Logs ==="
kubectl logs -n kafka -l strimzi.io/cluster=a2a-kafka --tail=50

- name: Cleanup
if: always()
working-directory: examples/cloud-deployment/scripts
shell: pwsh
run: .\cleanup.ps1 -Force
61 changes: 55 additions & 6 deletions examples/cloud-deployment/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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:

Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand All @@ -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
```

Expand Down
92 changes: 92 additions & 0 deletions examples/cloud-deployment/scripts/cleanup.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<#
.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",
[switch]$Force
)

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

if (-not $Force) {
$reply = Read-Host "Are you sure you want to continue? (y/N)"
if ($reply -notmatch "^[Yy]$") {
Write-Host "Cleanup cancelled"
exit 0
}
} else {
Write-Host "Running in forced mode, skipping confirmation." -ForegroundColor Yellow
}

Write-Host ""
Write-Host "Checking cluster connectivity..."
$null = kubectl cluster-info 2>$null
if ($LASTEXITCODE -eq 0) {
Write-Host "✓ Cluster reachable, deleting resources..." -ForegroundColor Green

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
} else {
Write-Host "⚠ Cluster not reachable, skipping resource deletion — resources will be removed with the cluster." -ForegroundColor Yellow
}
Comment on lines +47 to +76
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

If kubectl is not installed or not in the system PATH, calling kubectl cluster-info will throw a command-not-found exception in PowerShell. Since $LASTEXITCODE is not updated when a command-not-found error occurs, it will retain whatever value it had from the parent session. If that value was 0, the script will incorrectly enter the if block and attempt to run multiple kubectl delete commands, throwing a series of noisy errors.

Check if kubectl is available using Get-Command before executing it, similar to how it is done in deploy.ps1.

if (Get-Command kubectl -ErrorAction SilentlyContinue) {
    $null = kubectl cluster-info 2>$null
    if ($LASTEXITCODE -eq 0) {
        Write-Host "✓ Cluster reachable, deleting resources..." -ForegroundColor Green

        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
    } else {
        Write-Host "⚠ Cluster not reachable, skipping resource deletion — resources will be removed with the cluster." -ForegroundColor Yellow
    }
} else {
    Write-Host "⚠ kubectl not found, skipping resource deletion — resources will be removed with the cluster." -ForegroundColor Yellow
}


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"
Loading
Loading