# Arbitrary cluster constraints prototype
#### Prototype : https://github.com/anik120/operator-lifecycle-manager/commit/6e4998efd728d1d7622b94ce8e076d961d8eaa3f
## Communicating cluster constraints of a bundle to the resolver:
metadata/dependencies.yaml
```yaml
dependencies:
- type: olm.package
value:
packageName: foo
version: ">0.27.0"
- type: olm.clusterConstraints
value:
property: kubeVersion
comparisonOperator: ">"
value: 1.20
```
## Resolver resolving dependencies
Queries for configmap in the olm namespace.
```yaml=
apiVersion: v1
kind: ConfigMap
metadata:
name: olm-constraint-values
namespace: olm
data:
kubeVersion: "1.21"
ocpVersion: "4.7"
```
Resolver then adds the clause "predicate kubeVersion > 1.20 is true" and determines either true/false/failed using the value from the ConfigMap. The list of allowed comparison operators are:
* less than: "<"
* greater than: ">"
* equals: "="
* less than equals: "<="
* greater than equals: ">="
For example:
Since the example dependencies files mentions the following requirement:
```yaml=
- type: olm.clusterConstraints
value:
property: "kubeVersion"
comparisonOperator: ">"
value: "1.20"
```
and the value provided in the configmap is
```yaml=
data:
kubeVersion: "1.21"
ocpVersion: "4.7"
```
the predicate "kubeVersion > 1.20" resolves to true.
> Note: With this layout we implicitly get the and operator for dependencies, i.e when multiple cluster constraints are listed, they all have to be satisfied. If we want to include provisions for mentioning or operator for dependencies, we'll probably have to restructure the `Dependency struct` in a non breaking change way. Since we don't need that for 4.9, should we discuss that too in the first iteration of this epic?
## Observations from prototype:
* If configmap "olm-constraint-values" is not present, subscription condition has the following message
```yaml=
- message: configmaps "olm-constraint-values" not found
reason: ErrorPreventedResolution
status: "True"
type: ResolutionFailed
```
`Thoughts`: We probably need to include a job with the manifest deployed during olm installation that creates/fills in the confimap with some known cluster values that we know we'll need, eg kube version, ocp version, os etc.
`Cons`
* List can keep growing with increasing number of requests.
* Lot of edge cases while dealing with values entered through configmap. For example if the string quotes are missing for a numerical value:
```yaml=
- type: olm.clusterConstraints
value:
property: kubeVersion
comparisonOperator: ">"
value: 1.20
```
the configmap unmarshaller interprets as a number. But since the type definition that it is unmarshalled into looks like
```go=
type ClusterDependency struct {
// The property of the cluster, eg kubeVersion, os, arch etc
Property string `json:"property"`
// The comparison operator, one of ">" (greater than), "<" (less than), "=" (equals), ">=" (greater than equals), "<=" (less than equals), or "string"
ComparisonOperator string `json: "comparison_operator"`
// The value of the property on cluster, eg for kubeVersion, Value = "1.22"
Value string `json:"value"`
}
```
it fails at unmarshalling it. This could potentially cause headaches for creators of the configMap,(unless there's a way to force a configmap data values to be all string?)
## Suggestions:
* (njhale+joe): generic constrainst instead of olm.clusterConstraint
* (evan): represent cluster as a node in the solver (cluster contraints are contraints that are satisfied by the "cluster" node or not)
* (evan): how do we extend to operatorgroups, which are namespace-specific?
* (evan): how do we have properties that CVO owns (kube version) and properties that a user owns (override cvo property, or set a custom one (i.e. ibm may ship roks-only operators))
* (evan): does this still work if we teach olm about multiple clusters? (would we need to introduce a "cluster affinity" notion?)
* (evan): putting cluster constraints in dependencies.yaml works because we know there will be 1 unique "cluster" to satisfy them - is this something we can appropriately clarify in the docs, or do we need to go ahead with "AND" constraints so that it's clear that multiple non-cluster-constraints can be satisfied by multiple operators.
## Decision points:
* Use a templating engine to fill in values for configmap deployed during OLM installation.
* Use multiple configmaps to allow custom cluster values in addition to CVO managed configmap deployed during olm installation