cross

3 min read

The cross: block under a CRD declares which other CRDs this CRD observes. After the cross read runs, the observed data is available in templates as .cross.<as>.*.

crds:
  application:
    operatorBox:
      cross:
        - crd: database
          selector:
            name: "{{ .metadata.name }}-db"
          as: db

From that point on, anywhere in the application operatorBox:

{{ .cross.db.found }}                → "true" if the CR was found
{{ .cross.db.status.phase }}         → the observed CR's status.phase
{{ .cross.db.spec.storageGb }}       → the observed CR's spec field

Fields

FieldTypeRequiredDescription
crdstringone of crd/labelSelectorTarget CRD name — the key in spec.crds.
labelSelectormapone of crd/labelSelectorSelects a CRD by its labels instead of by name.
selectorobjectyesIdentifies which CR instance to observe.
asstringnoKey under .cross.* for template access. Defaults to crd.
sourceobjectnoFor cross-binary or cross-cluster reads. When absent, the informer cache is used.

selector:

Identifies which CR to read from the target CRD.

FieldTypeDescription
namestringCR name. Template expressions supported.
namespacestringCR namespace. Defaults to the current CR’s namespace.
matchLabelsmapLabel selector — picks the first matching CR (or all, when strategy: all). When set, name and namespace are ignored.
# By name
selector:
  name: "{{ .metadata.name }}-db"
  namespace: data-system

# By labels
selector:
  matchLabels:
    tier: platform
    tenant: "{{ .spec.tenant }}"

source: — cross-binary and cross-cluster reads

When the target CRD is in a different binary or cluster, declare source: to reach it over HTTP.

cross:
  - crd: loader
    selector:
      name: "{{ .metadata.name }}-loader"
    source:
      host: "http://loader-runtime.loader-system:8080"
      protocol: cr
      cacheFor: 10s
    as: loader
FieldTypeDefaultDescription
hoststringBase URL of the remote Orkestra runtime. Combined with type to build the endpoint URL.
typestringcrEndpoint type. One of cr, health, metrics, info, events.
endpointstringFully-qualified URL. When set, host and type are ignored. Template expressions supported.
namespacestringOverride namespace when building info/events URLs. Defaults to the CR’s namespace.
cacheForduration30sHow long to cache the result. Prevents calling the remote on every reconcile.
authobjectAuthentication for the remote endpoint.

Endpoint types

TypeURL builtWhat you get
cr/katalog/<crd>/cr/<ns>/<name>Full CR: spec, status, children, metrics
health/katalog/<crd>/healthOperator health state and last error
metrics/katalog/<crd>Operator-level metrics
info/katalog/<crd>CRD info: list, metrics, children
events/katalog/<crd>/cr/<ns>/<name>/eventsCR-scoped event stream

source.auth: — authentication

When the remote runtime requires a bearer token, declare it under auth:. Exactly one of token or secretRef must be set — ork validate rejects both set together.

source:
  host: "http://loader-runtime.loader-system:8080"
  auth:
    token: "$LOADER_TOKEN"    # ENV_VAR syntax supported

Or read the token from a Kubernetes Secret at startup:

source:
  host: "http://loader-runtime.loader-system:8080"
  auth:
    secretRef:
      name: loader-cross-token
      namespace: loader-system
      key: token
FieldTypeDescription
tokenstringBearer token. $ENV_VAR syntax resolves the value from the runtime’s environment at startup.
secretRef.namestringKubernetes Secret name.
secretRef.namespacestringKubernetes Secret namespace.
secretRef.keystringKey within the Secret whose value is the token.

secretRef is read once at startup and held in memory. If the Secret changes, a runtime restart is required to pick up the new value.


Same-binary vs cross-binary

When the target CRD is in the same Katalog, source: is unnecessary — the data comes from the informer cache with zero API calls:

# Same binary — no source: needed
cross:
  - crd: database
    selector:
      name: "{{ .metadata.name }}-db"
    as: db

When the target is in a different binary, source.host routes the read to the remote runtime’s live API. The result shape is the same either way — .cross.db.* works identically in templates regardless of where the data came from.

See ONCOP for the full cross-binary observation model.