E2E

4 min read

The E2E framework verifies that a pattern works against a real cluster before it is published. When e2e.yaml is present in a pattern directory, ork push runs it automatically and blocks publication if any expectation fails.

For the complete field reference — setup, expect, cluster, commands — see the E2E schema.


E2E status in ork patterns

ork patterns

Orkestra Registry
─────────────────────────────────────────────────────────────
NAME              LATEST  KIND     E2E  TAGS                    DESCRIPTION
postgres          v1.0.0  Katalog  ✓    postgres, database,...  A declarative PostgreSQL de...
kafka             v1.0.0  Katalog  ✓    kafka, messaging, s...  A declarative Apache Kafka ...
redis             v1.0.0  Katalog  ✓    redis, cache, key-v...  A declarative Redis deploym...
deployment-stack  v1.0.0  Katalog  ✗    deployment, service...  A declarative application d...

The E2E column shows when the published artifact carries io.orkestra.e2e.status=passed. means no E2E was run or it was force-pushed. Consumers can filter to verified patterns only:

ork patterns --e2e-passed

How it gates publication

# E2E runs automatically if e2e.yaml is present
ork push postgres:v14 ./patterns/postgres/

# Skip the gate — use --force
ork push postgres:v14 ./patterns/postgres/ --force

Whether the gate passed, was skipped, or was force-overridden, the result is baked into the OCI artifact as annotations:

io.orkestra.e2e.status     passed | skipped | forced
io.orkestra.e2e.duration   45s
io.orkestra.e2e.tested_at  2026-05-24T10:00:00Z
io.orkestra.e2e.runner     local | github-actions | gitlab-ci

ork inspect and ork patterns show this status for every pattern — a ✓ passed (45s · tested 2h ago) gives consumers confidence before they import.


Running E2E locally

Pull a pattern and run its E2E before importing it:

ork pull postgres:v14
ork e2e --file ~/.orkestra/registry/ghcr.io/orkestra-registry/postgres/v14/e2e.yaml

Or run against a pattern you are developing locally:

ork e2e --file ./patterns/postgres/e2e.yaml

By default, ork e2e provisions a temporary kind cluster, runs all expectations, then tears it down. Use --cluster to run against an existing kubeconfig context:

ork e2e --file ./e2e.yaml --cluster my-dev-context

e2e.yaml — pattern shape

A minimal E2E for a registry pattern. The setup block applies prerequisite namespaces or secrets before the operator starts; wait ensures they exist before the CR is applied.

apiVersion: orkestra.orkspace.io/v1
kind: E2E
metadata:
  name: postgres-e2e
  description: Verify the postgres pattern creates a StatefulSet and headless Service

spec:
  katalog: ./katalog.yaml
  crd: ./crd.yaml
  cr: ./cr.yaml

  cluster:
    provider: kind
    name: ork-e2e
    reuse: false

  setup:
    apply:
      - ./prereqs/namespace.yaml   # target namespace
    wait:
      - kind: Namespace
        name: databases
        timeout: 10s

  expect:
    - name: StatefulSet ready
      after: cr-applied
      timeout: 120s
      resources:
        - kind: StatefulSet
          name: my-postgres
          namespace: databases
          ready: true

    - name: Service exists
      after: cr-applied
      timeout: 30s
      resources:
        - kind: Service
          name: my-postgres
          namespace: databases

    - name: Cleanup verified
      after: cr-deleted
      timeout: 30s
      resources:
        - kind: StatefulSet
          name: my-postgres
          namespace: databases
          count: 0

→ Full field reference: E2E schema


Testing a multi-operator pattern

When a pattern contains more than one Katalog — a Komposer that imports several sources — one E2E per sub-Katalog keeps each test small and focused. A suite file at the category root imports them all, so a single ork e2e verifies the whole pattern before publication.

Layout in a registry pattern directory:

multi-tenancy/
  komposer.yaml
  e2e.yaml                         ← suite (pure aggregator)
  01-basic-namespacing/
    katalog.yaml  crd.yaml  cr.yaml  e2e.yaml
  02-cross-access-control/
    katalog.yaml  crd.yaml  cr.yaml  e2e.yaml
  03-shared-platform/
    katalog.yaml  crd.yaml  cr.yaml  e2e.yaml

The suite file:

apiVersion: orkestra.orkspace.io/v1
kind: E2E
metadata:
  name: multi-tenancy-suite
  description: >
    Runs all three multi-tenancy sub-examples in the same cluster.

imports:
  - ./01-basic-namespacing/e2e.yaml
  - ./02-cross-access-control/e2e.yaml
  - ./03-shared-platform/e2e.yaml

ork push discovers e2e.yaml at the pattern root and runs it. The suite provisions one cluster and runs each import in it sequentially — three sub-tests for the cost of one cluster lifecycle.

ork validate -f e2e.yaml reports each import with a ✓ before any cluster is involved:

✓ multi-tenancy-suite
    imports : 3 file(s)
      ✓ ./01-basic-namespacing/e2e.yaml
      ✓ ./02-cross-access-control/e2e.yaml
      ✓ ./03-shared-platform/e2e.yaml

3 import(s) valid

→ Full field reference: imports schema


E2E in CI

The io.orkestra.e2e.runner annotation records the environment. When ork push runs inside GitHub Actions, it records github-actions. Consumers can see that the pattern was verified in CI, not just locally.

Use --no-e2e to skip the gate in CI steps that only build artifacts without running tests:

ork push postgres:v14 ./patterns/postgres/ --no-e2e