Catalog Update Formulary

Background

File-based-catalogs (FBC) and catalog templates (templates) provide operator authors with standardized schemas to express operator upgrade graphs. However, without explicit tooling users require clear examples of how to achieve routine goals. This document is an attempt to establish a formulary of common operations, specifically with the intention of making these pieces automatable. This is in no way an exhaustive list.

Conventions

Formulae will be identified as FBC, basic catalog template (basic template), or semver catalog template (semver template). Schema manipulations will be modeled using YAML and yq. Wherever possible, example input will be limited to the relevant object hierarchies. Truncation is indicated by elipses (…) before and after the text.

Examples

For brevity, all formulae will refer to the same example, for semver template and FBC. For convenience, all semver bundle image pullspecs will express versions which match the bundle version (instead of SHAs).

FBC example

Formulae presume the following content is saved to the file fbc.yaml

--- defaultChannel: stable-v1.0 name: testoperator schema: olm.package --- entries:  - name: testoperator.v1.0.0  - name: testoperator.v1.0.1  skips:  - testoperator.v1.0.0 name: candidate-v1.0 package: testoperator schema: olm.channel --- entries:  - name: testoperator.v1.1.0  replaces: testoperator.v1.0.1  skips:  - testoperator.v1.0.0 name: candidate-v1.1 package: testoperator schema: olm.channel --- entries:  - name: testoperator.v1.0.1 name: fast-v1.0 package: testoperator schema: olm.channel --- entries:  - name: testoperator.v1.1.0  replaces: testoperator.v1.0.1 name: fast-v1.1 package: testoperator schema: olm.channel --- entries:  - name: testoperator.v1.0.1 name: stable-v1.0 package: testoperator schema: olm.channel 

basic template example

Formulae presume the following context is saved to the file basic.yaml

schema: olm.template.basic entries:  - schema: olm.package  name: testoperator  defaultChannel: stable  - schema: olm.channel  package: testoperator  name: stable  entries:  - name: testoperator.v0.1.0  - name: testoperator.v0.2.0  replaces: testoperator.v0.1.0  - schema: olm.bundle  image: quay.io/organization/testoperator:v0.1.0  - schema: olm.bundle  image: quay.io/organization/testoperator:v0.2.0 

semver template example

Formulae presume the following content is saved to the file semver.yaml

schema: olm.semver generateMajorChannels: false generateMinorChannels: true candidate:  bundles:  - image: quay.io/organization/testoperator:v1.0.0  - image: quay.io/organization/testoperator:v1.0.1  - image: quay.io/organization/testoperator:v1.1.0 fast:  bundles:  - image: quay.io/organization/testoperator:v1.0.1  - image: quay.io/organization/testoperator:v1.1.0 stable:  bundles:  - image: quay.io/organization/testoperator:v1.0.1 

Formulae

Adding a new bundle to an existing channel

FBC

Add a new testoperator.v1.1.1 edge to an existing candidate-v1.1 channel

yq eval 'select(.schema=="olm.channel" and .name == "candidate-v1.1").entries += [{"name" : "testoperator.v1.1.1"}]' fbc.yaml 

produces updated candidate-v1.1 channel:

... entries:  - name: testoperator.v1.1.0  replaces: testoperator.v1.0.1  skips:  - testoperator.v1.0.0  - name: testoperator.v1.1.1 name: candidate-v1.1 package: testoperator schema: olm.channel ... 

basic

Add a new testoperator.v0.2.1 bundle pullspec to the existing stable channel

yq eval 'select(.schema == "olm.template.basic").entries[] |= select(.schema == "olm.channel" and .name == "stable").entries += [{"name" : "testoperator.v0.2.1", "replaces": "testoperator.v0.2.0"}]' basic.yaml 

produces updated stable channel:

...  - schema: olm.channel  package: testoperator  name: stable  entries:  - name: testoperator.v0.1.0  - name: testoperator.v0.2.0  replaces: testoperator.v0.1.0  - name: testoperator.v0.2.1  replaces: testoperator.v0.2.0 ... 

semver

Add a new testoperator.v1.1.1 bundle pullspec to the Candidate channel archetype

yq eval '.candidate.bundles += [{"image" : "quay.io/organization/testoperator:v1.1.1"}]' semver.yaml 

produces updated Candidate archetype contents:

... candidate:  bundles:  - image: quay.io/organization/testoperator:v1.0.0  - image: quay.io/organization/testoperator:v1.0.1  - image: quay.io/organization/testoperator:v1.1.0  - image: quay.io/organization/testoperator:v1.1.1 ... 

FBC

Adding a new testoperator.v1.1.1 bundle version edge with a replaces link to its predecessor testoperator.v1.1.0 version which already exists in the channel.

yq eval 'select(.schema == "olm.channel" and .name == "candidate-v1.1").entries += [{"name" : "testoperator:v1.1.1", "replaces": "testoperator:v1.1.0"}]' fbc.yaml 

produces updated candidate-v1.1 channel:

... entries:  - name: testoperator.v1.1.0  replaces: testoperator.v1.0.1  skips:  - testoperator.v1.0.0  - name: testoperator:v1.1.1  replaces: testoperator:v1.1.0 name: candidate-v1.1 package: testoperator schema: olm.channel ... 

basic

Adding a new testoperator.v0.1.1 bundle version edge with a replaces link to its predecessor testoperator.v0.1.0 version which already exists in the channel.

yq eval 'select(.schema == "olm.template.basic").entries[] |= select(.schema == "olm.channel" and .name == "stable").entries += [{"name" : "testoperator:v0.1.1", "replaces": "testoperator:v0.1.0"}]' basic.yaml 

produces updated stable channel:

...  - schema: olm.channel  package: testoperator  name: stable  entries:  - name: testoperator.v0.1.0  - name: testoperator.v0.2.0  replaces: testoperator.v0.1.0  - name: testoperator:v0.1.1  replaces: testoperator:v0.1.0 ... 

Removing a specific bundle version

FBC

Remove the upgrade edge from the example candidate-v1.1 channel which refers to bundle version testoperator.v1.1.0.

yq eval 'del(select(.schema == "olm.channel" and .name == "candidate-v1.1" ).entries[]| select(.name == "testoperator.v1.1.0"))' fbc.yaml 

produces updated candidate-v1.1 channel:

... entries: [] name: candidate-v1.1 package: testoperator schema: olm.channel ... 

basic

Remove the upgrade edge from the example stable channel which refers to bundle version testoperator.v0.2.0.

yq eval 'select(.schema == "olm.template.basic").entries[] |= del(select(.schema == "olm.channel" and .name == "stable").entries[]| select(.name == "testoperator.v0.2.0"))' basic.yaml 

produces updated stable channel:

...  - schema: olm.channel  package: testoperator  name: stable  entries:  - name: testoperator.v0.1.0 ... 

Substituting a bundle version in the upgrade graph

FBC

For all graph edges, replaces instances of testoperator.v1.1.0 with a different bundle version testoperator.v1.1.0-CVE

yq '(.. | select(has("entries") and .entries[].name == "testoperator.v1.1.0" ).entries[]).name = "testoperator.v1.1.0-cve"' fbc.yaml 

produces updated channels:

--- defaultChannel: stable-v1.0 name: testoperator schema: olm.package --- entries:  - name: testoperator.v1.0.0  - name: testoperator.v1.0.1  skips:  - testoperator.v1.0.0 name: candidate-v1.0 package: testoperator schema: olm.channel --- entries:  - name: testoperator.v1.1.0-cve  replaces: testoperator.v1.0.1  skips:  - testoperator.v1.0.0 name: candidate-v1.1 package: testoperator schema: olm.channel --- entries:  - name: testoperator.v1.0.1 name: fast-v1.0 package: testoperator schema: olm.channel --- entries:  - name: testoperator.v1.1.0-cve  replaces: testoperator.v1.0.1 name: fast-v1.1 package: testoperator schema: olm.channel --- entries:  - name: testoperator.v1.0.1 name: stable-v1.0 package: testoperator schema: olm.channel 

basic

For all channels, replace instances of testoperator:v0.1.0 with testoperator:v0.1.0-CVE

yq '(..| select(. == "testoperator.v0.1.0")) |="testoperator.v0.1.0-CVE"' basic.yaml 

produces updated channels:

...  - schema: olm.channel  package: testoperator  name: stable  entries:  - name: testoperator.v0.1.0-CVE  - name: testoperator.v0.2.0  replaces: testoperator.v0.1.0-CVE ... 

semver

For all channels, replace instances of quay.io/organization/testoperator:v1.1.0 with quay.io/organization/testoperator:v1.1.0-CVE

yq '(..| select(has("image") and .image == "quay.io/organization/testoperator:v1.1.0")).image = "quay.io/organization/testoperator:v1.1.0-cve"' semver.yaml 

produces updated template:

schema: olm.semver generatemajorchannels: false generateminorchannels: true candidate:  bundles:  - image: quay.io/organization/testoperator:v1.0.0  - image: quay.io/organization/testoperator:v1.0.1  - image: quay.io/organization/testoperator:v1.1.0-cve fast:  bundles:  - image: quay.io/organization/testoperator:v1.0.1  - image: quay.io/organization/testoperator:v1.1.0-cve stable:  bundles:  - image: quay.io/organization/testoperator:v1.0.1 

Introducing a new replacement relationship in the upgrade graph

FBC

Substitute an existing ‘replaces’ link target for testoperator.v1.1.0 with a different bundle version testoperator.v1.0.0.

yq eval 'select(.schema == "olm.channel" and .name == "candidate-v1.1").entries |= [{"name" : "testoperator:v1.1.0", "replaces": "testoperator:v1.0.0"}]' fbc.yaml 

produces updated candidate-v1.1 channel:

... entries:  - name: testoperator:v1.1.0  replaces: testoperator:v1.0.0 name: candidate-v1.1 package: testoperator schema: olm.channel ... 

basic

Substitute an existing ‘replaces’ link target for testoperator.v0.2.0 with a different bundle version testoperator.v0.1.5.

yq eval '.entries[] |= select(.schema == "olm.channel" and .name == "stable").entries |= [{"name" : "testoperator:v0.2.0", "replaces": "testoperator:v0.1.5"}]' basic.yaml 

produces updated stable channel:

...  - schema: olm.channel  package: testoperator  name: stable  entries:  - name: testoperator:v0.2.0  replaces: testoperator:v0.1.5 ...