---
# System prepended metadata

title: Object References
tags: [schema]

---

---
tags: schema
---
# Object References

## Problem Statement

`ytt` templates that cover YAML dialects with inter-document references (like the KRM) rely on the author to understand and account for those references, manually.

Today, the Configuration Author that wants to apply a modification for object names extracts such a value as a Data Value and uses that reference in both the document containing the entity and _all_ of the paths in documents that refer to it.

That strategy becomes unduly burdensome in the case where the author wishes to apply a sweeping change like prefixing all object names with a string.

For example, the Kubernetes Resource Model (KRM) contains a web of object references. 
- `Deployment`s load configuration from `ConfigMap`s and `Secret`s;
- `RoleBinding`s mate-up to `Role`s with `ServiceAccount`s;
- CRDs can extend the KRM with their own custom relationships.
- ...

Any intent to modify the name (or namespace) of the referent must also explicitly update all references. Same is true for other identifiers (e.g. labels).


## Ideas

### Idea: Explicit Object Reference

In lieu of an explicit value for a given node, the author can make an object reference.

```yaml=
#! role.yaml
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: some-role
```
```yaml=
#@ load("@ytt:ref", "ref")
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: a-role-binding
roleRef: #@ ref.to(by=overlay.subset({"kind": "Role", "metadata": {"name": "some-role"}}), paths={"apiGroup": "apiVersion", "kind": "kind", "name": "metadata.name"})
```

... and when the referent is modified ...

```yaml=
#! name_prefix_patch.yaml

#@ load("@ytt:overlay", "overlay")
#@overlay/match by=overlay.all, expects="1+"
---
metadata:
  #@overlay/replace via=lambda left, right: right+left
  name: PREFIX-
```

... the reference is updated ...

```yaml=
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: PREFIX-a-role-binding
roleRef:
  apiGroup: rbac.authorization.k8s.io/v1
  kind: Role
  name: PREFIX-some-role
```

### Idea: Reference Type in Schema

The author can declare a node of type "reference"

```yaml=
#@ load("@ytt:ref", "ref")
#
#@schema/definition name="rbac.authorization.k8s.io/v1/RoleBinding"
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: ""
#@schema/type "reference"
roleRef: ...
```
...

