Files
wehub-resource-sync 4b6817381b
CI (OpenClaw E2E) / openclaw test (push) Has been cancelled
CI / coverage-report (push) Has been cancelled
CI / test-kubernetes (push) Has been cancelled
CI / should-run-thorough (push) Has been cancelled
CI / test-thorough (cloudwatch-demo) (push) Has been cancelled
CI / test-thorough (flink-ecs) (push) Has been cancelled
CI / test-thorough (upstream-lambda) (push) Has been cancelled
CI / test-thorough (prefect-ecs-fargate) (push) Has been cancelled
Release / build-binaries (zip, opensre.exe, onefile, windows-latest, windows-x64) (push) Has been cancelled
Benchmark image — build + push to ECR (any adapter) / build + push (push) Has been cancelled
CI / quality (ubuntu-latest) (push) Has been cancelled
CI / test (tools-runtime) (push) Has been cancelled
CI / test (e2e-general) (push) Has been cancelled
CI / test (cli-runtime) (push) Has been cancelled
CI / test (e2e-provider-and-openclaw) (push) Has been cancelled
CI / test (integrations-and-misc) (push) Has been cancelled
Release / verify (push) Has been cancelled
Release / build-python-dist (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, macos-15-intel, darwin-x64) (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, macos-latest, darwin-arm64) (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04, linux-x64) (push) Has been cancelled
Release / publish-release (push) Has been cancelled
Release / publish-main-release (push) Has been cancelled
Interactive Shell Live (PR + post-merge) / turn-checks (no-LLM) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Interactive Shell Live (PR + post-merge) / turn-live shard ${{ matrix.shard_index }} (push) Has been cancelled
Release / prepare (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04-arm, linux-arm64) (push) Has been cancelled
Synthetic Deterministic Tests / Synthetic offline (deterministic) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:10:45 +08:00

13 KiB

Kubernetes Test Case — Reference Architecture

Overview

This test case validates an end-to-end ETL pipeline running as Kubernetes Jobs, covering both the happy path and failure path (intentional schema error injection). It runs in two modes:

Mode Cluster S3 Observability CI
Local (test_local.py) kind (local) Real AWS S3 Yes (GitHub Actions)
Datadog local (test_datadog.py) kind (local) Real AWS S3 Datadog via Helm Manual
EKS (test_eks.py, trigger_alert.py) AWS EKS Real AWS S3 Datadog via Helm + Lambda trigger Manual

Architecture Diagram

┌──────────────────────────────────────────────────────────────────────────────┐
│  TEST RUNNER (CI / local machine)                                            │
│                                                                              │
│  test_local.py / test_eks.py / trigger_alert.py                              │
│  infrastructure_sdk/local.py  ·  infrastructure_sdk/eks.py                  │
└────────────────────────┬─────────────────────────────────────────────────────┘
                         │ orchestrates
                         ▼
┌──────────────────────────────────────────────────────────────────────────────┐
│  KUBERNETES CLUSTER  (kind locally  /  AWS EKS in cloud)                     │
│  Namespace: tracer-test                                                      │
│                                                                              │
│  ┌─────────────────────────────────────────────────────────────────────────┐ │
│  │  Job: etl-extract   (PIPELINE_STAGE=extract)                            │ │
│  │  Image: tracer-k8s-test:latest                                          │ │
│  │  → reads  s3://landing-bucket/<run-id>/input.json                       │ │
│  │  → writes s3://landing-bucket/<run-id>/extracted.json                   │ │
│  └──────────────────────────────┬──────────────────────────────────────────┘ │
│                                 │ sequential (test runner waits for job)     │
│  ┌──────────────────────────────▼──────────────────────────────────────────┐ │
│  │  Job: etl-transform  (PIPELINE_STAGE=transform)                         │ │
│  │  Happy path  → validates schema, converts amount to cents               │ │
│  │  Error path  → REQUIRED_FIELDS contains unknown field → DomainError     │ │
│  │  → reads  s3://landing-bucket/<run-id>/extracted.json                   │ │
│  │  → writes s3://landing-bucket/<run-id>/transformed.json  (happy only)   │ │
│  └──────────────────────────────┬──────────────────────────────────────────┘ │
│                                 │ (happy path only)                          │
│  ┌──────────────────────────────▼──────────────────────────────────────────┐ │
│  │  Job: etl-load  (PIPELINE_STAGE=load)                                   │ │
│  │  → reads  s3://landing-bucket/<run-id>/transformed.json                 │ │
│  │  → writes s3://processed-bucket/<run-id>/output.json                    │ │
│  └─────────────────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────────────┘

                         │ real read/write
                         ▼
┌──────────────────────────────────────────────────────────────────────────────┐
│  AWS S3                                                                      │
│  ┌───────────────────────────────┐   ┌────────────────────────────────────┐  │
│  │  tracer-k8s-landing-*         │   │  tracer-k8s-processed-*            │  │
│  │  <run-id>/input.json          │   │  <run-id>/output.json              │  │
│  │  <run-id>/extracted.json      │   └────────────────────────────────────┘  │
│  │  <run-id>/transformed.json    │                                           │
│  └───────────────────────────────┘                                           │
└──────────────────────────────────────────────────────────────────────────────┘

── EKS / Datadog paths only ────────────────────────────────────────────────────

┌──────────────────────────────────────────────────────────────────────────────┐
│  AWS Lambda  (trigger_lambda/handler.py)                                     │
│  POST /trigger               → happy path (valid data)                       │
│  POST /trigger?inject_error  → error path (bad data, forces DomainError)     │
│  Fronted by API Gateway                                                      │
└───────────────────────────┬──────────────────────────────────────────────────┘
                            │ submits kubectl jobs to EKS
                            ▼ (same K8s jobs as above)

┌──────────────────────────────────────────────────────────────────────────────┐
│  Datadog Agent  (Helm chart: datadog/datadog)                                │
│  • collects container logs from all pods                                     │
│  • collects kube-state-metrics (job.failed counter)                          │
│  Monitors:                                                                   │
│  ├── Metric alert: kubernetes_state.job.failed > 0  → @slack-devs-alerts     │
│  └── Log alert:    "PIPELINE_ERROR" in logs          → @slack-devs-alerts     │
└──────────────────────────────────────────────────────────────────────────────┘

Component Descriptions

Pipeline Code (pipeline_code/)

A self-contained Python ETL application packaged as a single Docker image. The active stage is selected at runtime via the PIPELINE_STAGE environment variable.

Module Role
stages/__init__.py Dispatcher — routes to extract / transform / load
stages/extract.py Reads raw JSON from S3 landing bucket, writes to staging key
stages/transform.py Validates schema against REQUIRED_FIELDS, converts amount to cents
stages/load.py Reads staged data, writes final record to processed bucket
domain.py Validation + transformation business logic
schemas.py InputRecord / ProcessedRecord dataclasses
errors.py PipelineErrorDomainError / SystemError hierarchy
config.py Reads all config from environment variables
adapters/s3.py S3 read/write with correlation_id + processed_at metadata

The image is built from pipeline_code/Dockerfile (Python 3.11-slim) and tagged tracer-k8s-test:latest.

Kubernetes Manifests (k8s_manifests/)

Plain YAML templates with {{PLACEHOLDER}} variables replaced at test runtime by infrastructure_sdk/local.py. One manifest per pipeline stage plus an error variant for transform.

Manifest Stage Notes
job-extract.yaml extract Reads LANDING_BUCKET + S3_KEY
job-transform.yaml transform (success) backoffLimit: 0 — fails fast
job-transform-error.yaml transform (failure) Same spec, different labels
job-load.yaml load Also writes PROCESSED_BUCKET
namespace.yaml tracer-test namespace

Helm Chart (helm/)

A thin Helm wrapper around the same ETL job for EKS / Datadog deployments. Exposes job.injectError to switch between happy and error paths without maintaining two separate manifests.

Infrastructure SDK (infrastructure_sdk/)

File Responsibility
local.py kind cluster lifecycle, Docker build/load, kubectl apply, job polling, Datadog Helm install, monitor CRUD
eks.py EKS cluster + node group creation/teardown, ECR push, IAM roles, API Gateway + Lambda deployment

Test Entry Points

File When to run
test_local.py CI (GitHub Actions) + local dev. kind cluster, real S3.
test_datadog.py Manual. kind + Datadog Helm. Requires DD_API_KEY / DD_APP_KEY.
test_eks.py Manual. Full EKS deployment + teardown. Requires full AWS credentials + Datadog keys.
trigger_alert.py Manual. Fires alerts against an already-running EKS cluster via Lambda.

Data Flow (Happy Path)

Test Runner
    │
    ├─ uploads input.json to s3://landing/<run-id>/input.json
    │
    ├─ kubectl apply job-extract
    │       Job reads input.json
    │       Writes extracted.json  →  s3://landing/<run-id>/extracted.json
    │
    ├─ kubectl apply job-transform
    │       Job reads extracted.json
    │       Validates schema, converts amount*100
    │       Writes transformed.json  →  s3://landing/<run-id>/transformed.json
    │
    ├─ kubectl apply job-load
    │       Job reads transformed.json
    │       Writes output.json  →  s3://processed/<run-id>/output.json
    │
    └─ asserts output.json exists + content matches expected record

Data Flow (Error / Failure Path)

Test Runner
    │
    ├─ uploads malformed or schema-breaking input.json
    │
    ├─ kubectl apply job-extract  (succeeds — no validation here)
    │
    ├─ kubectl apply job-transform-error
    │       Job reads extracted.json
    │       Schema validation fails  →  DomainError("missing required field: X")
    │       Job exits non-zero  →  K8s Job status: Failed
    │       Container logs: "PIPELINE_ERROR ..."
    │
    └─ asserts:
           job status == Failed
           (Datadog path) log alert fires within timeout
           (Datadog path) metric alert fires within timeout

Environment Variables

Variable Used by Description
PIPELINE_STAGE All stages Selects which stage to run (extract/transform/load)
LANDING_BUCKET extract, transform S3 bucket for raw + staging data
PROCESSED_BUCKET load S3 bucket for final output
S3_KEY extract S3 key of the input file
PIPELINE_RUN_ID All stages Unique ID — used as S3 key prefix
REQUIRED_FIELDS transform Comma-separated list of required fields (error injection: add unknown field)
AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY All stages AWS credentials (injected via Job env or IAM role on EKS)
DD_API_KEY / DD_APP_KEY Datadog paths Datadog credentials
INJECT_ERROR Helm chart path Set to "true" to trigger the error path via Helm