Ref Parsers¶
Ref-parsers are CEL-based rules that scan rendered Kubernetes resources and extract dependency edges.
How Parsers Work¶
For each rendered resource (entity):
- Evaluate each parser's predicate — Does this parser apply to this resource?
- If the predicate matches: evaluate each pick rule — Extract ref definitions
- Build ref edges from the extracted definitions
Parser File Format¶
Parsers are defined in YAML files:
ref-parsers:
- predicate: '<CEL expression>' # When to apply this parser
priority: 0 # Higher wins; negative values behave like weak fallback ownership
tag: [<tag>, ...] # Tags for all refs from this parser
label: '<label>' # Label for all refs
reverse: false # Reverse edge direction?
pick:
- cel: '<CEL expression>' # Extraction rule (returns []RefDefinition)
label: '<override-label>' # Override parser-level label
attributes: [<key:value>, ...] # Additional attributes
Predicate¶
The predicate is a CEL expression that determines which resources this parser processes. It has access to all entity variables (gvk, kind, name, ns, etc.).
# Match all resources
predicate: "true"
# Match only Deployments
predicate: 'gvk == "apps/v1/Deployment"'
# Match resources with ownerReferences
predicate: 'has(entity.metadata.ownerReferences) && entity.metadata.ownerReferences.size() > 0'
The priority Field¶
priority controls how strongly a parser participates in ref-ownership matching:
0is the normal default strength- higher values win over lower values when multiple apps match
- negative values only participate for still-untracked / cluster-only resources at that stage
For app-defined parser groups under global.hydra.refs, prefer placing priority on the group next to tag. That group-level value becomes the default for all contained ref-parsers, and an individual parser can still override it when needed.
Pick Rules¶
Each pick rule is a CEL expression that returns a list of RefDefinition objects using the refBuilder() API:
refBuilder() API¶
refBuilder() → Start building a ref
.incoming(endpoint) → Create ref pointing TO this resource
.outgoing(endpoint) → Create ref pointing FROM this resource
.label(string) → Set the ref label
.tag(string) → Add a tag
.desc(string) → Set description
.attribute(key, value) → Add an attribute
Endpoint Functions¶
id(gvk, ns, name) → Reference by resource ID
idString("gvk", "ns", "name") → Reference by string literals
ref(provider, value) → Non-ID reference (external)
Example: Self-Reference¶
Every resource gets an incoming ref to itself (enables graph connectivity):
Example: Owner References¶
Extract dependencies from Kubernetes ownerReferences:
ref-parsers:
- predicate: 'has(entity.metadata.ownerReferences) && entity.metadata.ownerReferences.size() > 0'
reverse: true
label: owner
pick:
- cel: |
entity.metadata.ownerReferences.filter(o, has(o.controller) && o.controller).map(o,
refBuilder().outgoing(id(o.apiVersion + "/" + o.kind, ns, o.name))
.attribute("kubernetes:ownerController", "true")
)
Example: Namespace Dependency¶
Every namespaced resource depends on its Namespace:
ref-parsers:
- predicate: 'namespaced && ns != ""'
label: namespace
pick:
- cel: '[refBuilder().outgoing(id("v1/Namespace", "", ns))]'
The reverse Flag¶
When reverse: true, the edge direction is stored inverted. This is used for ownerReferences where the child stores the ref but the logical direction is parent → child.
See Also¶
- Writing Custom Refs — Create your own parsers
- CEL: Functions — refBuilder() and id() reference
- CEL: Variables — Available variables in predicates