Skip to content

Commit

Permalink
Update compound-bundle-constraints enhancement
Browse files Browse the repository at this point in the history
Signed-off-by: Tyler Slaton <[email protected]>
  • Loading branch information
Tyler Slaton committed Jan 26, 2022
1 parent 51b42b3 commit e7ac0b8
Showing 1 changed file with 129 additions and 100 deletions.
229 changes: 129 additions & 100 deletions enhancements/compound-bundle-constraints.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
title: compound-bundle-constraints
title: compound-dependency-selectors
authors:
- "@estroz"
reviewers:
Expand All @@ -19,7 +19,7 @@ replaces:
superseded-by:
---

# compound-bundle-constraints
# compound-dependency-selectors

## Release Signoff Checklist

Expand Down Expand Up @@ -131,27 +131,25 @@ about successful and failed resolution as with current "simple" constraints.

**Note**: see ["Implementation History"](#implementation-history) for proof-of-concept info.

I propose the new [`olm.constraint` property][arb-constraints] fields `all`, `any`, and `none`
to specify conjunction, disjunction, and negation compound constraints, respectively.
Their value type is a struct containing a list of constraints such as GVK,
package, or any compound constraint listed above under a `constraints` key.
I propose the new [`olm.constraint` property][arb-constraints] fields `all`, `any`, and `not`
to specify conjunction, disjunction, and negation compound constraints, respectively. Their value
type is a struct containing a list of constraints such as GVK, package, or any compound constraint
listed above under a `constraints` key. This new `olm.constraint` key should be defined in
`dependencies.yaml` but can also be defined in `properties.yaml`.

I also propose that `olm.gvk.required` and `olm.package.required` are redefined as
`gvk` and `package` fields to align with other properties under `olm.constraint`:

```yaml
schema: olm.bundle
name: baz.v1.0.0
properties:
- type: olm.constraint
value:
message: Package bar v1.0.0+ is needed for...
failureMessage: Package bar v1.0.0+ is needed for...
package:
name: bar
versionRange: '>=1.0.0'
- type: olm.constraint
value:
message: GVK Buf/v1 is needed for...
failureMessage: GVK Buf/v1 is needed for...
gvk:
group: bufs.example.com
version: v1
Expand All @@ -170,80 +168,53 @@ against an installable object's properties.

#### Conjunction and disjunction

These compound constraint types are evaluated following their logical definitions.
These compound constraint types are evaluated following their logical definitions.

**Note**: Before proceeding, it is important to keep in mind that these constraint are only solvable by
a single operator, not multiple. In order to define multiple operators multiple `olm.constraint`
values will need to be specified in the properties.

This is an example of a conjunctive constraint of two packages and one GVK,
i.e. they must all be satisfied by installed bundles:

```yaml
schema: olm.bundle
name: baz.v1.0.0
properties:
- type: olm.constraint
value:
message: All are required for Baz because...
all:
constraints:
- message: Package bar is needed for...
package:
name: bar
versionRange: '>=1.0.0'
- message: GVK Buf/v1 is needed for...
gvk:
group: bufs.example.com
version: v1
kind: Buf
type: olm.constraint
value:
failureMessage: All are required for Baz because...
all:
constraints:
- failureMessage: Package bar is needed for...
package:
name: bar
versionRange: '>=1.0.0'
- failureMessage: GVK Buf/v1 is needed for...
gvk:
group: bufs.example.com
version: v1
kind: Buf
```

This is an example of a disjunctive constraint of three versions of the same GVK,
i.e. at least one must be satisfied by installed bundles:

```yaml
schema: olm.bundle
name: baz.v1.0.0
properties:
- type: olm.constraint
value:
message: Any are required for Baz because...
any:
constraints:
- gvk:
group: foos.example.com
version: v1beta1
kind: Foo
- gvk:
group: foos.example.com
version: v1beta2
kind: Foo
- gvk:
group: foos.example.com
version: v1
kind: Foo
```

#### Negation

Negation is worth further explanation, since at first glance its semantics
are unclear in this context. The negation is really instructing the resolver
to remove any possible solution that includes a particular GVK, package
at a version, or satisfies some child compound constraint from the result set.

This is an example of a negation constraint of one version of a GVK,
i.e. this GVK cannot be provided by any bundle in the result set:

```yaml
schema: olm.bundle
name: baz.v1.0.0
properties:
- type: olm.constraint
value:
message: Cannot be required for Baz because...
none:
constraints:
- gvk:
group: foos.example.com
version: v1alpha1
kind: Foo
type: olm.constraint
value:
failureMessage: Any are required for Baz because...
any:
constraints:
- gvk:
group: foos.example.com
version: v1beta1
kind: Foo
- gvk:
group: foos.example.com
version: v1beta2
kind: Foo
- gvk:
group: foos.example.com
version: v1
kind: Foo
```

#### Nested compound constraints
Expand All @@ -256,38 +227,96 @@ This is an example of a disjunction of conjunctions, where one, the other, or bo
can be satisfy the constraint.

```yaml
schema: olm.bundle
name: baz.v1.0.0
properties:
- type: olm.constraint
value:
message: Required for Baz because...
any:
constraints:
- all:
constraints:
- package:
name: foo
versionRange: '>=1.0.0'
- gvk:
group: foos.example.com
version: v1
kind: Foo
- all:
constraints:
- package:
name: foo
versionRange: '<1.0.0'
- gvk:
group: foos.example.com
version: v1beta1
kind: Foo
type: olm.constraint
value:
failureMessage: Required for Baz because...
any:
constraints:
- all:
constraints:
- package:
name: foo
versionRange: '>=1.0.0'
- gvk:
group: foos.example.com
version: v1
kind: Foo
- all:
constraints:
- package:
name: foo
versionRange: '<1.0.0'
- gvk:
group: foos.example.com
version: v1beta1
kind: Foo
```

The maximum raw size of an `olm.constraint` is 64KB to limit resource exhaustion attacks.
See [this issue][json-limit-issue] for details on why size is limited and not depth.
This limit can be changed at a later date if necessary.

#### Negation

Negation is worth further explanation, since at first glance its semantics
are unclear in this context. The negation is really instructing the resolver
to remove any possible solution that includes a particular GVK, package
at a version, or satisfies some child compound constraint from the result set.

If you define a negation constraint on a resource, then that resource cannot
be used as a solution. This can be useful if you want to have a constraint
that cannot be solved by a specific GVK or bundle. Most of the time, you will
want to use this as a nested constraint. This is because the negation constraint
in the root will not actually restrict anything.

**Remember, negation is only used to say "this package cannot be used as a
solution". It does not mean that the bundle is restricted from successfully
installing if the negated package is already installed on the cluster**

The most common use case for negation is if you want to depend on a GVK but don't
want a certain package/version of a package to provide it. In the below example, if the
solution were to include a package that would provide the `bufs.example.com/v1` GVK then
the `not` would remove it only if it was package `foo` with version `>=v1.0.0`. If no other
solutions are available then the bundle constraints would be considered unsolvable.

```yaml
type: olm.constraint
value:
message: All are required because...
all:
constraints:
- all:
constraints:
- failureMessage: GVK Buf/v1 required for...
gvk:
group: bufs.example.com
version: v1
kind: Buf
- not:
constraints:
- failureMessage: Package foo version >=1.0.0 cannot be required for...
package:
name: foo
versionRange: '>=1.0.0'
```

While less useful, here is an example of a negation constraint of one version of
a GVK under the root. Again, this says that this GVK cannot be provided by any bundle
in the result set. Since there are no other constraints, anything will solve this
constraint and thus it will be installable:

```yaml
type: olm.constraint
value:
failureMessage: Cannot be required for Baz because...
not:
constraints:
- gvk:
group: foos.example.com
version: v1alpha1
kind: Foo
```

#### Changes to OLM's resolver

The [resolver package][olm-resolver-primitives] supplies the primitives "and" and "or" already,
Expand Down

0 comments on commit e7ac0b8

Please sign in to comment.