owned this note
owned this note
Published
Linked with GitHub
# Property Projection
## Background
During dependency resolution, all relationships between installed and available operators are translated into a system of constraints.
For the purposes of this translation, each operator is described by zero or more **properties**. A **property** is a statement of fact about an operator, like "*provides v1beta1 of the Cog API*," or "*comes from the package named 'sprocket'*," or "*has version 2.1.9*".
An operator's dependencies are expressed as **constraints**, which are true-or-false questions that can be answered by inspecting an operator's **properties**, for example, "*comes from the package named 'astro' and has version 2.0.0 or newer*". For each of an operator's dependencies, a successful resolution outcome must include at least one operator that satisfies its constraints. If an operator has two dependencies, they may or may not both be satisfied by the same operator.
Operator catalogs serve the properties and dependencies of the operators they contain. However, once an operator is installed (i.e., is represented by a ClusterServiceVersion object within a cluster), these properties and dependencies can only be inferred if there is a direct association from the ClusterServiceVersion to an operator catalog, via a Subscription. Without this information, manually-installed operators may not be able to satisfy the dependencies of resolved operators. In worse cases, resolution may not have enough information to recognize conflicts.
## Proposal
When a bundle is converted into InstallPlan steps, the annotation `operatorframework.io/properties` is added to any ClusterServiceVersion resources. This annotation should not already exist on a manifest, because it is prefixed by operatorframework.io and its name is defined for the first time in this document. If it does, its value is overwritten and a warning is logged. It's important that the value of the annotation be precisely the properties used during resolution.
For each operator in the result, dependency resolution returns the unmodified properties as an opaque string. If a bundle is inline, these are directly wired up to the InstallPlan step conversion. If a bundle needs to be unpacked, the properties blob is written to a new, optional field on the BundleLookup entries of InstallPlan statuses, which in turn will be wired up to the bundle-to-InstallPlan-step conversion.
### API Change (Backwards-Compatible)
```go
type BundleLookup struct {
// ...
Properties string `json:"properties,omitempty"`
}
```
### Serialization
The value of the annotation is a JSON object. If the top-level key "properties" is present, its corresponding value must be a JSON array, and each element in the array must be a JSON object that encodes a single property [as defined in operator-registry](https://github.com/operator-framework/operator-registry/blob/2e3070479c4a64064a56caf8d36250923080a95f/pkg/registry/types.go#L171).
```json
{
"properties": [
{
"type": "olm.package",
"value": {
"packageName": "floperator",
"version": "1.2.3"
}
},
{
"type": "olm.gvk",
"value": {
"group": "cuebernetes.io",
"version": "v1alpha8",
"kind": "Chalk"
}
}
]
}
```
Future updates to the representation of properties on-cluster, in bundles, and in indices should converge to a single serialized form for properties, if practical, to facilitate interoperability.
### Backwards Compatibility
When the resolver encounters an existing ClusterServiceVersion without the properties annotation, its effective value is synthesized based on the ClusterServiceVersion's spec, and should at least contain a representation of the operator's provided APIs. These occurrences should be logged, but only once per resolution attempt, not once per ClusterServiceVersion. As part of a future enhancement, the synthesized annotation may be persisted to the ClusterServiceVersion resource. That is out of scope for this proposal.
### Dependency Projection
The projection of dependencies onto cluster state is out of scope. It is possible to encode dependencies as properties, and in that case, dependency projection would be satisfied by property projection, but that is also out of scope.
Dependency projection is important for determining whether the current cluster state is consistent under resolution, but that is not a feature that exists today. It is also necessary for correct behavior in namespaces containing a mixture of operators that have been installed as dependencies and operators that have been installed standalone (without a subscription). In the absence of projected dependencies, certain dependencies (required APIs) of can be inferred from ClusterServiceVersion specs.