Skip to content

Commit 02458bf

Browse files
authored
Merge pull request #5748 from toumorokoshi/feature/clarify-multiple-kind-references
clarifying schema for multi-kind object references
2 parents c232cd4 + ac7999c commit 02458bf

File tree

1 file changed

+126
-7
lines changed

1 file changed

+126
-7
lines changed

contributors/devel/sig-architecture/api-conventions.md

Lines changed: 126 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -874,11 +874,6 @@ Examples:
874874

875875
## Object references
876876

877-
Object references should either be called `fooName` if referring to an object of
878-
kind `Foo` by just the name (within the current namespace, if a namespaced
879-
resource), or should be called `fooRef`, and should contain a subset of the
880-
fields of the `ObjectReference` type.
881-
882877
Object references on a namespaced type should usually refer only to objects in
883878
the same namespace. Because namespaces are a security boundary, cross namespace
884879
references can have unexpected impacts, including:
@@ -900,8 +895,133 @@ clearly described and the permissions issues should be resolved.
900895
This could be done with a double opt-in (an opt-in from both the referrer and the refer-ee) or with secondary permissions
901896
checks performed in admission.
902897

903-
TODO: Plugins, extensions, nested kinds, headers
898+
### Naming of the reference field
899+
900+
The name of the reference field should be of the format "{field}Ref", with "Ref" always included in the suffix.
901+
902+
The "{field}" component should be named to indicate the purpose of the reference. For example, "targetRef" in an
903+
endpoint indicates that the object reference specifies the target.
904+
905+
It is okay to have the "{field}" component indicate the resource type. For example, "secretRef" when referencing
906+
a secret. However, this comes with the risk of the field being a misnomer in the case that the field is expanded to
907+
reference more than one type.
908+
909+
### Referencing resources with multiple versions
910+
911+
Most resources will have multiple versions. For example, core resources
912+
will undergo version changes as it transitions from alpha to GA.
913+
914+
Controllers should assume that a version of a resource may change, and include appropriate error handling.
915+
916+
### Handling of resources that do not exist
917+
918+
There are multiple scenarios where a desired resource may not exist. Examples include:
919+
920+
- the desired version of the resource does not exist.
921+
- race condition in the bootstrapping of a cluster resulting a resource not yet added.
922+
- user error.
923+
924+
Controllers should be authored with the assumption that the referenced resource may not exist, and include
925+
error handling to make the issue clear to the user.
926+
927+
### Object References Examples
928+
929+
The following sections illustrate recommended schemas for various object references scenarios.
930+
931+
The schemas outlined below are designed to enable purely additive fields as the types of referencable
932+
objects expand, and therefore are backwards compatible.
904933

934+
For example, it is possible to go from a single resource type to multiple resource types without
935+
a breaking change in the schema.
936+
937+
#### Single resource reference
938+
939+
A single kind object reference is straightforward in that the controller can hard-code most qualifiers needed to identify the object. As such as the only value needed to be provided is the name (and namespace, although cross-namespace references are discouraged):
940+
941+
```yaml
942+
# for a single resource, the suffix should be Ref, with the field name
943+
# providing an indication as to the resource type referenced.
944+
secretRef:
945+
name: foo
946+
# namespace would generally not be needed and is discouraged,
947+
# as explained above.
948+
namespace: foo-namespace
949+
```
950+
951+
This schema should only be used when the intention is to always have the reference only be to a single resource.
952+
If extending to multiple resource types is possible, use the [multiple resource reference](#multiple-resource-reference).
953+
954+
##### Controller behavior
955+
956+
The operator is expected to know the version, group, and resource name of the object it needs to retrieve the value from, and can use the discovery client or construct the API path directly.
957+
958+
#### Multiple resource reference
959+
960+
Multi-kind object references are used when there is a bounded set of valid resource types that a reference can point to.
961+
962+
As with a single-kind object reference, the operator can supply missing fields, provided that the fields that are present are sufficient to uniquely identify the object resource type among the set of supported types.
963+
964+
```yaml
965+
# guidance for the field name is the same as a single resource.
966+
fooRef:
967+
group: sns.services.k8s.aws
968+
resource: topics
969+
name: foo
970+
namespace: foo-namespace
971+
```
972+
973+
Although not always necessary to help a controller identify a resource type, “group” is included to avoid ambiguity when the resource exists in multiple groups. It also provides clarity to end users and enables copy-pasting of a reference without the referenced type changing due to a different controller handling the reference.
974+
975+
##### Controller behavior
976+
977+
The operator can store a map of (group,resource) to the version of that resource it desires. From there, it can construct the full path to the resource, and retrieve the object.
978+
979+
It is also possible to have the controller choose a version that it finds via the discovery client. However, as schemas can vary across different versions
980+
of a resource, the controller must also handle these differences.
981+
982+
#### Generic object reference
983+
984+
A generic object reference is used when the desire is to provide a pointer to some object to simplify discovery for the user. For example, this could be used to reference a target object for a `core.v1.Event` that occurred.
985+
986+
With a generic object reference, it is not possible to extract any information about the referenced object aside from what is standard (e.g. ObjectMeta). Since any standard fields exist in any version of a resource, it is possible to not include version in this case:
987+
988+
```yaml
989+
fooObjectRef:
990+
group: operator.openshift.io
991+
resource: openshiftapiservers
992+
name: cluster
993+
# namespace is unset if the resource is cluster-scoped, or lives in the
994+
# same namespace as the referrer.
995+
```
996+
997+
##### Controller behavior
998+
999+
The operator would be expected to find the resource via the discovery client (as the version is not supplied). As any retrievable field would be common to all objects, any version of the resource should do.
1000+
1001+
#### Field reference
1002+
1003+
A field reference is used when the desire is to extract a value from a specific field in a referenced object.
1004+
1005+
Field references differ from other reference types, as the operator has no knowledge of the object prior to the reference. Since the schema of an object can differ for different versions of a resource, this means that a “version” is required for this type of reference.
1006+
1007+
```yaml
1008+
fooFieldRef:
1009+
version: v1 # version of the resource
1010+
# group is elided in the ConfigMap example, since it has a blank group in the OpenAPI spec.
1011+
resource: configmaps
1012+
fieldPath: data.foo
1013+
```
1014+
1015+
The fieldPath should point to a single value, and use [the recommended field selector notation](#selecting-fields) to denote the field path.
1016+
1017+
##### Controller behavior
1018+
1019+
In this scenario, the user will supply all of the required path elements: group, version, resource, name, and possibly namespace.
1020+
As such, the controller can construct the API prefix and query it without the use of the discovery client:
1021+
1022+
```
1023+
/apis/{group}/{version}/{resource}/
1024+
```
9051025

9061026
## HTTP Status codes
9071027

@@ -1456,4 +1576,3 @@ Example: "must be greater than \`request\`".
14561576
be less than 256", "must be greater than or equal to 0". Do not use words
14571577
like "larger than", "bigger than", "more than", "higher than", etc.
14581578
* When specifying numeric ranges, use inclusive ranges when possible.
1459-

0 commit comments

Comments
 (0)