|
| 1 | +--- |
| 2 | +title: run-bundle |
| 3 | +authors: |
| 4 | + - "@jmrodri" |
| 5 | +reviewers: |
| 6 | + - "@joelanford" |
| 7 | + - "@estroz" |
| 8 | + - "@kevinrizza" |
| 9 | + - "@ecordell" |
| 10 | + - "@shawn-hurley" |
| 11 | +approvers: |
| 12 | + - "@joelanford" |
| 13 | + - "@estroz" |
| 14 | + - "@ecordell" |
| 15 | + - "@shawn-hurley" |
| 16 | +creation-date: 2020-05-07 |
| 17 | +last-updated: 2020-05-07 |
| 18 | +status: implementable |
| 19 | +see-also: |
| 20 | +replaces: |
| 21 | +superseded-by: |
| 22 | + |
| 23 | +--- |
| 24 | + |
| 25 | +# Run Bundle |
| 26 | + |
| 27 | +## Release Signoff Checklist |
| 28 | + |
| 29 | +- [X] Enhancement is `implementable` |
| 30 | +- [X] Design details are appropriately documented from clear requirements |
| 31 | +- [X] Test plan is defined |
| 32 | +- [X] Graduation criteria for dev preview, tech preview, GA |
| 33 | + |
| 34 | +## Open Questions |
| 35 | + |
| 36 | +1. We currently check OLM installation status with `operator-sdk olm status`. |
| 37 | + Can we change that to using the discovery API? |
| 38 | + * Based on discussions, using the discovery API is the way to go. |
| 39 | + |
| 40 | +2. How do we handle --mode= flag on registry add? |
| 41 | + * When adding a bundle to an empty index, default to **semver** |
| 42 | + * When adding a bundle to a provided index, default to **replaces** |
| 43 | + * Should the add mode be configurable on the CLI? **optional flag**; |
| 44 | + not in an example right now |
| 45 | + |
| 46 | +3. Is there no case we want to enable permissive mode? |
| 47 | + * No, always keep permissive disabled. |
| 48 | + |
| 49 | +## Summary |
| 50 | + |
| 51 | +Enhance the Operator SDK `run` command to support the new bundle format. |
| 52 | + |
| 53 | +## Motivation |
| 54 | + |
| 55 | +One of the primary goals of the Operator SDK is to make it easy for operator |
| 56 | +developers to run and test their operators with Operator Lifecycle |
| 57 | +Manager (OLM). There currently exists a `run --olm` command which supports the |
| 58 | +packagemanifest format. In order to add support for the new bundle format, we |
| 59 | +are migrating to subcommands on the run command instead of increasing the |
| 60 | +number of flags. |
| 61 | + |
| 62 | +### Goals |
| 63 | + |
| 64 | +Provide a command line that works with bundle image format. |
| 65 | + |
| 66 | +### Non-Goals |
| 67 | + |
| 68 | +This design does not cover the replacement of run --olm with run |
| 69 | +packagemanifest. The change to `run packagemanifest` is covered by |
| 70 | +[OSDK-1126](https://issues.redhat.com/browse/OSDK-1126). |
| 71 | + |
| 72 | +For now we will assume the existing registry DB located at `/database/index.db`. |
| 73 | +In a follow-up design we can investigate having the SDK use the labels to |
| 74 | +detect the DB path. |
| 75 | + |
| 76 | +Another non-goal, is that `run bundle` is **NOT** intended to help users build |
| 77 | +and manage indexes. It is an opinionated command to help users test simple |
| 78 | +bundle-based execution scenarios with ephemeral indexes. We are intentionally |
| 79 | +**NOT** supporting advanced use cases. |
| 80 | + |
| 81 | +## Proposal |
| 82 | + |
| 83 | +### Implementation Details/Notes/Constraints [optional] |
| 84 | + |
| 85 | +The Operator SDK currently supports running an operator with OLM using the |
| 86 | +`run` command with the `--olm` flag. The existing command only supports the |
| 87 | +package manifest format. This enhancement will add a new subcommand, `bundle`, |
| 88 | +to the `run` command. This new command, `run bundle`, will support the new |
| 89 | +bundle format. More information about the different formats can be found at |
| 90 | +the URLs below: |
| 91 | + |
| 92 | + * Operator bundles: https://github.com/operator-framework/operator-registry/blob/master/docs/design/operator-bundle.md |
| 93 | + * Package manifests format: https://github.com/operator-framework/operator-registry/tree/v1.5.3/#manifest-format |
| 94 | + |
| 95 | +The idea is to consolidate the run command into different subcommands to make |
| 96 | +things easier to understand and eliminate flag bloat. |
| 97 | + |
| 98 | + * `run --local` - exists today; converting to a subcommand will be covered by [OSDK-1126](https://issues.redhat.com/browse/OSDK-1126) |
| 99 | + * `run packagemanifest` - covered by [OSDK-1126](https://issues.redhat.com/browse/OSDK-1126) |
| 100 | + * `run bundle` - covered by this design document |
| 101 | + |
| 102 | +#### Command Line Interface |
| 103 | +The new command line will look as follows: |
| 104 | + |
| 105 | +``` |
| 106 | +operator-sdk run bundle <bundle-image> [--index-image=] [--namespace=] [--install-mode=(AllNamespace|OwnNamespace|SingleNamespace=)] |
| 107 | +``` |
| 108 | + |
| 109 | +* `<bundle-image>` is a positional argument that specifies the bundle image. |
| 110 | +* `[--index-image=]` is an optional flag that specifies the index image. |
| 111 | + * If `--index-image` is not provided, default to |
| 112 | + `quay.io/operator-framework/upstream-opm-builder` |
| 113 | + * If `--index-image` is provided, use the provided value |
| 114 | +* `[--namespace=]` is an optional flag that specifies the namespace to install |
| 115 | + the operator. It will default to the `KUBECONFIG` context. |
| 116 | +* `[--install-mode=]` is an optional flag that specifies the |
| 117 | + [OLM install mode](https://red.ht/2YK0ksD). |
| 118 | + * We support 3 modes: |
| 119 | + * AllNamespaces |
| 120 | + * OwnNamespace |
| 121 | + * SingleNamespace=ns1 |
| 122 | + * NOTE: if ns1 is the same as the operator's namespace, a warning will be |
| 123 | + printed |
| 124 | + * When `--install-mode` is not supplied, the default precedence order is: |
| 125 | + * `OperatorGroup`, if it already exists |
| 126 | + * `AllNamespaces`, if the CSV supports it |
| 127 | + * `OwnNamespace`, if the CSV supports it |
| 128 | + * If the CSV does not support either of these, `--install-mode` flag |
| 129 | + will be **required** |
| 130 | + |
| 131 | +#### Assumptions |
| 132 | +Like the existing `run` command, we **assume** the following: |
| 133 | + |
| 134 | + 1. OLM is already installed |
| 135 | + 1. kube API is available with the permissions to create resources |
| 136 | + 1. kubelet can see and pull the provided images (i.e. bundle and index) |
| 137 | + 1. If an index image is provided, we assume that it has: |
| 138 | + * bash, so we can change the entrypoint |
| 139 | + * dependencies required for `opm registry add` so we can inject |
| 140 | + the bundle into the DB |
| 141 | + * the existing registry DB located at `/database/index.db` |
| 142 | + |
| 143 | +#### Example UX Scenarios |
| 144 | + |
| 145 | +Running the following scenarios results in different results. While not an |
| 146 | +exhaustive list, these are some example uses of the `run bundle` command. |
| 147 | + |
| 148 | +* `operator-sdk run bundle <bundle-image>` |
| 149 | +* `operator-sdk run bundle <bundle-image> --namespace foo` |
| 150 | +* `operator-sdk run bundle <bundle-image> --namespace foo --install-mode SingleNamespace=bar` |
| 151 | +* `operator-sdk run bundle <bundle-image> --install-mode SingleNamespace=bar` |
| 152 | + |
| 153 | +It is important to remember that the presence of an OperatorGroup in the |
| 154 | +namespace can affect the how `run bundle` behaves. Let's look at a couple scenarios. |
| 155 | + |
| 156 | +* Given an operator that supports install modes `OwnNamespace` and |
| 157 | + `SingleNamespace` being installed into a namespace with *no* OperatorGroup. |
| 158 | + The `run bundle` command would behave as follows: |
| 159 | + * `operator-sdk run bundle <bundle-image>` would install into the default |
| 160 | + namespace configured in the `KUBECONFIG` context. An OperatorGroup would be |
| 161 | + created targeting the same install namespace. |
| 162 | + * `operator-sdk run bundle <bundle-image> --namespace foo --install-mode SingleNamespace=bar` |
| 163 | + would install into namespace `foo`. An OperatorGroup would be created |
| 164 | + targeting the `bar` namespace. |
| 165 | +* Given an operator that supports install modes `AllNamespaces`, `OwnNamespace`, |
| 166 | + and `SingleNamespace`, being installed into a namespace with an existing |
| 167 | + OperatorGroup that targets all namespaces: |
| 168 | + * `operator-sdk run bundle <bundle-image>` would install into the default |
| 169 | + namespace configured in the `KUBECONFIG` context. The operator would watch |
| 170 | + all namespaces. |
| 171 | + * `operator-sdk run bundle <bundle-image> --namespace foo --install-mode SingleNamespace=bar` |
| 172 | + would install into namespace `foo`. The operator would watch namespace |
| 173 | + `bar`. |
| 174 | + |
| 175 | +As you can see the presence of the OperatorGroup will take precedence. If the |
| 176 | +OperatorGroup does not support a version an error condition will occur. The `run |
| 177 | +bundle` command will return with a non-zero exit status and log the errors. |
| 178 | + |
| 179 | +#### Simple Example |
| 180 | + |
| 181 | +Let's take the simplest example from above. |
| 182 | + |
| 183 | +``` |
| 184 | +operator-sdk run bundle <bundle-image> |
| 185 | +``` |
| 186 | + |
| 187 | +What happens when the above is invoked? |
| 188 | + |
| 189 | + 1. Since `--index-image` was not provided, assign variable `registryImage` |
| 190 | + equal to `quay.io/operator-framework/upstream-opm-builder` |
| 191 | + 1. Create pod using `registryImage`, set container command (entrypoint) to: |
| 192 | + ``` |
| 193 | + /bin/bash -c ‘ \ |
| 194 | + /bin/mkdir -p /database && \ |
| 195 | + /bin/opm registry add -d /database/index.db -b {.BundleImage} && \ |
| 196 | + /bin/opm registry serve -d /database/index.db’ |
| 197 | + ``` |
| 198 | + 1. If pod fails, clean it up, and error out with message of unsupported |
| 199 | + index image. Also capture the pod's logs for debugging. |
| 200 | + 1. Create GRPC CatalogSource, pointing to <pod-name>.<namespace>:50051 |
| 201 | + 1. Create OperatorGroup, only if it does not exist, since `--install-mode` was |
| 202 | + not supplied, defaults to `AllNamespaces` (assuming operator supports this |
| 203 | + mode). |
| 204 | + 1. Create Subscription |
| 205 | + 1. Operator installed into the default namespace defined by KUBECONFIG |
| 206 | + 1. Verify operator is installed. |
| 207 | + 1. Log what happened and final state (e.g. operator is running in namespace |
| 208 | + X, watching namespace(s) Y. |
| 209 | + 1. Log command to execute to cleanup operator. |
| 210 | + 1. Exit with success (leaving operator running) |
| 211 | +
|
| 212 | +#### Complex Example |
| 213 | +
|
| 214 | +Now let's look at one of the more complex examples: |
| 215 | +
|
| 216 | +``` |
| 217 | +operator-sdk run bundle <bundle-image> --namespace foo --install-mode SingleNamespace=bar |
| 218 | +``` |
| 219 | +
|
| 220 | + 1. Since `--index-image` was not provided, assign variable `registryImage` |
| 221 | + equal to `quay.io/operator-framework/upstream-opm-builder` |
| 222 | + 1. Create pod using `registryImage`, set container command (entrypoint) to: |
| 223 | + ``` |
| 224 | + /bin/bash -c ‘ \ |
| 225 | + /bin/mkdir -p /database && \ |
| 226 | + /bin/opm registry add -d /database/index.db -b {.BundleImage} && \ |
| 227 | + /bin/opm registry serve -d /database/index.db’ |
| 228 | + ``` |
| 229 | + 1. If pod fails, clean it up, and error out with message of unsupported |
| 230 | + index image. Also capture the pod's logs for debugging. |
| 231 | + 1. Create GRPC CatalogSource, pointing to <pod-name>.<namespace>:50051 |
| 232 | + 1. Creates an OperatorGroup in and targetting namespace `bar`. |
| 233 | + 1. Create Subscription |
| 234 | + 1. Operator installed into the default namespace `foo` |
| 235 | + 1. Verify operator is installed. |
| 236 | + 1. Log what happened and final state (e.g. operator is running in namespace |
| 237 | + `foo`, watching namespace `bar`. |
| 238 | + 1. Log command to execute to cleanup operator. |
| 239 | + 1. Exit with success (leaving operator running) |
| 240 | +
|
| 241 | +#### Prototype Links |
| 242 | +
|
| 243 | + * PR upstream-opm-builder.Dockerfile: add bash and ca-certificates |
| 244 | + https://github.com/operator-framework/operator-registry/pull/320 |
| 245 | + * Examples setup script: |
| 246 | + https://gist.github.com/joelanford/f7a7d89977638547b410db3eafc35a62 |
| 247 | + * Modified upstream-opm-builder: |
| 248 | + https://github.com/joelanford/operator-registry/blob/9f8b6b19709a333ede683b89ac0fda1abf9b14b8/upstream-opm-builder.Dockerfile#L16-L17 |
| 249 | + * Bundle runner Helm chart: |
| 250 | + https://github.com/joelanford/bundle-runner |
| 251 | + * Static validation sync: |
| 252 | + https://docs.google.com/document/d/1Lf9foKtObj1ACk67a_0BNn7rupWAHEejZ6vynJggBCw/edit# |
| 253 | + * Bundle format: |
| 254 | + https://github.com/operator-framework/operator-registry/blob/master/docs/design/operator-bundle.md |
| 255 | +
|
| 256 | +### Risks and Mitigations |
| 257 | +
|
| 258 | +If we do not get the modified |
| 259 | +[upstream-opm-builder](https://github.com/operator-framework/operator-registry/blob/master/docs/design/operator-bundle.md) |
| 260 | +referenced above the following assumptions will not work: |
| 261 | +
|
| 262 | + 1. if image doesn't have bash, we can't modify the entrypoint |
| 263 | + 1. if opm is building index images without bash, then there will be no index |
| 264 | + images we support |
| 265 | +
|
| 266 | +## Design Details |
| 267 | +
|
| 268 | +### Test Plan |
| 269 | +
|
| 270 | + * add tests for `internal/olm/operator/operator.go` |
| 271 | + * investigate adding e2e tests for `run bundle`, use the `run --olm` [e2e tests](https://github.com/operator-framework/operator-sdk/blob/master/test/integration/operator_olm_test.go) |
| 272 | + as an example. |
| 273 | + * manual testing of `run bundle` will be done as well |
| 274 | +
|
| 275 | +### Graduation Criteria |
| 276 | +
|
| 277 | +The `run bundle` command will come in as non-alpha and be ready to use once |
| 278 | +merged. |
| 279 | +
|
| 280 | +### Upgrade / Downgrade Strategy |
| 281 | +
|
| 282 | +### Version Skew Strategy |
| 283 | +
|
| 284 | +N/A |
| 285 | +
|
| 286 | +## Implementation History |
| 287 | +
|
| 288 | +20200515 - Answer semver; capture all the PR feedback |
| 289 | +20200508 - Do not wrap CLI command in document |
| 290 | +20200508 - Updated questions, clarified CLI flags, defined UX, detailed examples |
| 291 | +20200507 - Initial proposal to add `run bundle` subcommand |
| 292 | +
|
| 293 | +## Drawbacks |
| 294 | +
|
| 295 | +N/A |
| 296 | +
|
| 297 | +## Alternatives |
| 298 | +
|
| 299 | +There is a potential alternative to handling failed pods. Instead of cleaning up |
| 300 | +the failed pod and capturing the logs, we could keep the failed pod around to |
| 301 | +allow developers to capture the logs and debug the issue. |
| 302 | +
|
| 303 | +A flag, --skip-cleanup, could be added to skip cleaning up failed pods. This is |
| 304 | +similar to scorecard. |
| 305 | +
|
| 306 | +## Infrastructure Needed [optional] |
| 307 | +
|
| 308 | +N/A |
0 commit comments