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
4 changes: 4 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ on:
- main
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
build:
runs-on: ubuntu-latest
Expand Down
58 changes: 58 additions & 0 deletions .github/workflows/harness-image.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: Harness Worker Image

on:
push:
branches: [main, TOOL-33-test-worker]
paths:
- "harness/**"
- "build.gradle"
- "settings.gradle"
- ".github/workflows/harness-image.yml"
release:
types: [published]
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/conductor-oss/java-sdk/harness-worker
tags: |
type=raw,value=latest
type=raw,value=${{ github.event.release.tag_name }},enable=${{ github.event_name == 'release' }}

- name: Build and push
uses: docker/build-push-action@v6
with:
context: .
file: ./harness/Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
4 changes: 4 additions & 0 deletions .github/workflows/integration-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ permissions:
statuses: write
checks: write

concurrency:
group: ${{ github.workflow }}-${{ github.event.workflow_run.head_branch }}
cancel-in-progress: true

jobs:
integration-tests:
runs-on: ubuntu-latest
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/osv-scanner.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ permissions:
contents: read
security-events: write

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
scan-pr:
uses: "google/osv-scanner-action/.github/workflows/osv-scanner-reusable-pr.yml@v2.3.3"
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
10 changes: 10 additions & 0 deletions harness/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
FROM eclipse-temurin:21-jdk AS build
WORKDIR /app
COPY . .
RUN ./gradlew :harness:installDist -x test --no-daemon

FROM eclipse-temurin:21-jre
WORKDIR /app
COPY --from=build /app/harness/build/install/harness/lib/ ./lib/

ENTRYPOINT ["java", "-cp", "lib/*", "io.orkes.conductor.harness.HarnessMain"]
73 changes: 73 additions & 0 deletions harness/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Java SDK Worker Harness

A self-feeding worker harness that runs indefinitely. On startup it registers five simulated tasks (`java_worker_0` through `java_worker_4`) and the `java_simulated_tasks_workflow`, then runs two background services:

- **WorkflowGovernor** -- starts a configurable number of `java_simulated_tasks_workflow` instances per second (default 2), indefinitely.
- **SimulatedTaskWorkers** -- five task handlers, each with a codename and a default sleep duration. Each worker supports configurable delay types, failure simulation, and output generation via task input parameters. The workflow chains them in sequence: quickpulse (1s) → whisperlink (2s) → shadowfetch (3s) → ironforge (4s) → deepcrawl (5s).

All resource names use a `java_` prefix so multiple SDK harnesses (C#, Python, Go, etc.) can coexist on the same cluster.

## Local Run

```bash
# From the repository root
CONDUCTOR_SERVER_URL=https://your-cluster.example.com/api \
CONDUCTOR_AUTH_KEY=your-key \
CONDUCTOR_AUTH_SECRET=your-secret \
./gradlew :harness:run
```

## Docker

### Build

From the repository root:

```bash
docker build -f harness/Dockerfile -t java-sdk-harness .
```

### Run

```bash
docker run -d \
-e CONDUCTOR_SERVER_URL=https://your-cluster.example.com/api \
-e CONDUCTOR_AUTH_KEY=$CONDUCTOR_AUTH_KEY \
-e CONDUCTOR_AUTH_SECRET=$CONDUCTOR_AUTH_SECRET \
-e HARNESS_WORKFLOWS_PER_SEC=4 \
java-sdk-harness
```

### Multiplatform Build and Push

Build for both `linux/amd64` and `linux/arm64` and push to GHCR:

```bash
docker buildx build \
--platform linux/amd64,linux/arm64 \
-f harness/Dockerfile \
-t ghcr.io/conductor-oss/java-sdk/harness-worker:latest \
--push .
```

After pushing a new image with the same tag, restart the K8s deployment to pull it:

```bash
kubectl rollout restart deployment/java-sdk-harness-worker -n $NS
kubectl rollout status deployment/java-sdk-harness-worker -n $NS
```

## Environment Variables

| Variable | Required | Default | Description |
|---|---|---|---|
| `CONDUCTOR_SERVER_URL` | yes | -- | Conductor API base URL |
| `CONDUCTOR_AUTH_KEY` | no | -- | Orkes auth key |
| `CONDUCTOR_AUTH_SECRET` | no | -- | Orkes auth secret |
| `HARNESS_WORKFLOWS_PER_SEC` | no | 2 | Workflows to start per second |
| `HARNESS_BATCH_SIZE` | no | 20 | Thread count per worker (controls polling concurrency) |
| `HARNESS_POLL_INTERVAL_MS` | no | 100 | Milliseconds between poll cycles |

## Kubernetes

See [manifests/README.md](manifests/README.md) for deployment instructions.
18 changes: 18 additions & 0 deletions harness/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
plugins {
id 'java'
id 'application'
}

application {
mainClass = 'io.orkes.conductor.harness.HarnessMain'
}

repositories {
mavenCentral()
}

dependencies {
implementation project(':conductor-client')
implementation project(':orkes-client')
implementation "ch.qos.logback:logback-classic:1.5.6"
}
130 changes: 130 additions & 0 deletions harness/manifests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# Kubernetes Manifests

This directory contains Kubernetes manifests for deploying the Java SDK harness worker to the certification clusters.

## Prerequisites

**Set your namespace environment variable:**
```bash
export NS=your-namespace-here
```

All kubectl commands below use `-n $NS` to specify the namespace. The manifests intentionally do not include hardcoded namespaces.

## Files

| File | Description |
|---|---|
| `deployment.yaml` | Deployment (single file, works on all clusters) |
| `configmap-aws.yaml` | Conductor URL + auth key for certification-aws |
| `configmap-azure.yaml` | Conductor URL + auth key for certification-az |
| `configmap-gcp.yaml` | Conductor URL + auth key for certification-gcp |
| `secret-conductor.yaml` | Conductor auth secret (placeholder template) |

## Quick Start

### 1. Create the Conductor Auth Secret

The `CONDUCTOR_AUTH_SECRET` must be created as a Kubernetes secret before deploying.

```bash
kubectl create secret generic conductor-credentials \
--from-literal=auth-secret=YOUR_AUTH_SECRET \
-n $NS
```

If the `conductor-credentials` secret already exists in the namespace (e.g. from the e2e-testrunner-worker or the C# harness), it can be reused as-is.

See `secret-conductor.yaml` for more details.

### 2. Apply the ConfigMap for Your Cluster

```bash
# AWS
kubectl apply -f manifests/configmap-aws.yaml -n $NS

# Azure
kubectl apply -f manifests/configmap-azure.yaml -n $NS

# GCP
kubectl apply -f manifests/configmap-gcp.yaml -n $NS
```

### 3. Deploy

```bash
kubectl apply -f manifests/deployment.yaml -n $NS
```

### 4. Verify

```bash
# Check pod status
kubectl get pods -n $NS -l app=java-sdk-harness-worker

# Watch logs
kubectl logs -n $NS -l app=java-sdk-harness-worker -f
```

## Building and Pushing the Image

From the repository root:

```bash
# Build for both amd64 and arm64 and push to GHCR
docker buildx build \
--platform linux/amd64,linux/arm64 \
-f harness/Dockerfile \
-t ghcr.io/conductor-oss/java-sdk/harness-worker:latest \
--push .
```

After pushing a new image with the same tag, restart the deployment to pull it:

```bash
kubectl rollout restart deployment/java-sdk-harness-worker -n $NS
kubectl rollout status deployment/java-sdk-harness-worker -n $NS
```

## Tuning

The harness worker accepts these optional environment variables (set in `deployment.yaml`):

| Variable | Default | Description |
|---|---|---|
| `HARNESS_WORKFLOWS_PER_SEC` | 2 | Workflows to start per second |
| `HARNESS_BATCH_SIZE` | 20 | Thread count per worker (controls polling concurrency) |
| `HARNESS_POLL_INTERVAL_MS` | 100 | Milliseconds between poll cycles |

Edit `deployment.yaml` to change these, then re-apply:

```bash
kubectl apply -f manifests/deployment.yaml -n $NS
```

## Troubleshooting

### Pod not starting

```bash
kubectl describe pod -n $NS -l app=java-sdk-harness-worker
kubectl logs -n $NS -l app=java-sdk-harness-worker --tail=100
```

### Secret not found

```bash
kubectl get secret conductor-credentials -n $NS
```

## Resource Limits

Default resource allocation:
- **Memory**: 256Mi (request) / 512Mi (limit)
- **CPU**: 100m (request) / 500m (limit)

Adjust in `deployment.yaml` based on workload. Higher `HARNESS_WORKFLOWS_PER_SEC` values may need more CPU/memory.

## Service

The harness worker does **not** need a Service or Ingress. It connects to Conductor via outbound HTTP polling. All communication is outbound.
13 changes: 13 additions & 0 deletions harness/manifests/configmap-aws.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
# ConfigMap for certification-aws cluster
# Contains Conductor connection details specific to this cluster
apiVersion: v1
kind: ConfigMap
metadata:
name: java-sdk-harness-config
# namespace: xxxxx # supply this in kubectl command
labels:
app: java-sdk-harness-worker
data:
CONDUCTOR_SERVER_URL: "https://certification-aws.orkesconductor.io/api"
CONDUCTOR_AUTH_KEY: "7ba9d0ec-247b-11f1-8d42-ea3efeda41b2"
13 changes: 13 additions & 0 deletions harness/manifests/configmap-azure.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
# ConfigMap for certification-az cluster
# Contains Conductor connection details specific to this cluster
apiVersion: v1
kind: ConfigMap
metadata:
name: java-sdk-harness-config
# namespace: xxxxx # supply this in kubectl command
labels:
app: java-sdk-harness-worker
data:
CONDUCTOR_SERVER_URL: "https://certification-az.orkesconductor.io/api"
CONDUCTOR_AUTH_KEY: "bf170d61-2797-11f1-833e-4ae04d100a03"
13 changes: 13 additions & 0 deletions harness/manifests/configmap-gcp.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
# ConfigMap for certification-gcp cluster
# Contains Conductor connection details specific to this cluster
apiVersion: v1
kind: ConfigMap
metadata:
name: java-sdk-harness-config
# namespace: xxxxx # supply this in kubectl command
labels:
app: java-sdk-harness-worker
data:
CONDUCTOR_SERVER_URL: "https://certification-gcp.orkesconductor.com/api"
CONDUCTOR_AUTH_KEY: "e6c1ac61-286b-11f1-be01-c682b5750c3a"
Loading
Loading