Skip to content

Commit b0d35d4

Browse files
committed
add /operator-catalog plugin to build operator index image
1 parent b536984 commit b0d35d4

File tree

3 files changed

+366
-0
lines changed

3 files changed

+366
-0
lines changed

PLUGINS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ OLM (Operator Lifecycle Manager) plugin for operator management and debugging
123123
- **`/olm:diagnose` `[operator-name] [namespace] [--fix] [--cluster]`** - Diagnose and optionally fix common OLM and operator issues
124124
- **`/olm:install` `<operator-name> [namespace] [channel] [source] [--approval=Automatic|Manual]`** - Install a day-2 operator using Operator Lifecycle Manager
125125
- **`/olm:list` `[namespace] [--all-namespaces]`** - List installed operators in the cluster
126+
- **`/olm:opm` `<action> [arguments...]`** - Execute opm (Operator Package Manager) commands for building and managing operator catalogs
126127
- **`/olm:search` `[query] [--catalog <catalog-name>]`** - Search for available operators in catalog sources
127128
- **`/olm:status` `<operator-name> [namespace]`** - Get detailed status and health information for an operator
128129
- **`/olm:uninstall` `<operator-name> [namespace] [--remove-crds] [--remove-namespace]`** - Uninstall a day-2 operator and optionally remove its resources

docs/data.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,12 @@
328328
"synopsis": "/olm:list [namespace] [--all-namespaces]",
329329
"argument_hint": "[namespace] [--all-namespaces]"
330330
},
331+
{
332+
"name": "opm",
333+
"description": "Execute opm (Operator Package Manager) commands for building and managing operator catalogs",
334+
"synopsis": "/olm:opm build-index-image <catalog-path> <index-image-tag> [--cacheless] [--arch=<arch>] [--base-image=<image>] [--builder-image=<image>]",
335+
"argument_hint": "<action> [arguments...]"
336+
},
331337
{
332338
"name": "search",
333339
"description": "Search for available operators in catalog sources",

plugins/olm/commands/opm.md

Lines changed: 359 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,359 @@
1+
---
2+
description: Execute opm (Operator Package Manager) commands for building and managing operator catalogs
3+
argument-hint: <action> [arguments...]
4+
---
5+
6+
## Name
7+
olm:opm
8+
9+
## Synopsis
10+
```
11+
/olm:opm build-index-image <catalog-path> <index-image-tag> [--cacheless] [--arch=<arch>] [--base-image=<image>] [--builder-image=<image>]
12+
/olm:opm build-semver-index-image <semver-template-file> <index-image-tag> [--cacheless] [--arch=<arch>] [--base-image=<image>] [--builder-image=<image>]
13+
/olm:opm generate-semver-template <bundle-list> [--output=<file>] [--major=true|false] [--minor=true|false]
14+
/olm:opm list packages <index-ref>
15+
/olm:opm list channels <index-ref> [package-name]
16+
/olm:opm list bundles <index-ref> [package-name]
17+
```
18+
19+
## Description
20+
The `olm:opm` command provides a unified interface to `opm` (Operator Package Manager) operations for building and managing operator catalog indexes. It supports building catalog indexes, generating semver templates, and querying catalog contents.
21+
22+
## Arguments
23+
- `$1`: **action** - The action to perform:
24+
- `build-index-image`: Build an index from an existing catalog directory
25+
- `build-semver-index-image`: Build an index from a semver template
26+
- `generate-semver-template`: Generate a semver template file
27+
- `list`: List catalog contents (requires second argument: `packages`, `channels`, or `bundles`)
28+
- `$2+`: Additional arguments specific to each action (see Actions section below)
29+
30+
## Actions
31+
32+
### build-index-image
33+
Build an operator catalog index image from an existing catalog directory.
34+
35+
**Synopsis:**
36+
```
37+
/olm:opm build-index-image <catalog-path> <index-image-tag> [--cacheless] [--arch=<arch>] [--base-image=<image>] [--builder-image=<image>]
38+
```
39+
40+
**Arguments:**
41+
- `$2`: **catalog-path** - Path to the catalog directory containing the index configuration
42+
- `$3`: **index-image-tag** - Full image tag for the resulting index image (e.g., `quay.io/myorg/mycatalog:v1.0.0`)
43+
- `--cacheless`: Optional flag to build a cacheless image (uses `scratch` as base image; `--base-image` and `--builder-image` are ignored when this is set)
44+
- `--arch=<arch>`: Optional architecture specification (default: `multi` for multi-arch build; can specify single arch like `amd64`, `arm64`, `ppc64le`, `s390x`)
45+
- `--base-image=<image>`: Optional base image for the index (default: `quay.io/operator-framework/opm:latest`; ignored if `--cacheless` is set)
46+
- `--builder-image=<image>`: Optional builder image (default: `quay.io/operator-framework/opm:latest`; ignored if `--cacheless` is set)
47+
48+
**Examples:**
49+
```
50+
/olm:opm build-index-image catalog quay.io/myorg/mycatalog:v1.0.0
51+
/olm:opm build-index-image catalog quay.io/myorg/mycatalog:v1.0.0 --cacheless
52+
/olm:opm build-index-image catalog quay.io/myorg/mycatalog:v1.0.0 --arch=amd64
53+
```
54+
55+
### build-semver-index-image
56+
Build a multi-architecture operator catalog index image using the semver template format.
57+
58+
**Synopsis:**
59+
```
60+
/olm:opm build-semver-index-image <semver-template-file> <index-image-tag> [--cacheless] [--arch=<arch>] [--base-image=<image>] [--builder-image=<image>]
61+
```
62+
63+
**Arguments:**
64+
- `$2`: **semver-template-file** - Path to the semver template configuration file (e.g., `catalog-config.yaml`)
65+
- `$3`: **index-image-tag** - Full image tag for the resulting index image (e.g., `quay.io/myorg/mycatalog:v1.0.0`)
66+
- `--cacheless`: Optional flag to build a cacheless image (uses `scratch` as base image; `--base-image` and `--builder-image` are ignored when this is set)
67+
- `--arch=<arch>`: Optional architecture specification (default: `multi` for multi-arch build; can specify single arch like `amd64`, `arm64`, `ppc64le`, `s390x`)
68+
- `--base-image=<image>`: Optional base image for the index (default: `quay.io/operator-framework/opm:latest`; ignored if `--cacheless` is set)
69+
- `--builder-image=<image>`: Optional builder image (default: `quay.io/operator-framework/opm:latest`; ignored if `--cacheless` is set)
70+
71+
**Examples:**
72+
```
73+
/olm:opm build-semver-index-image catalog-config.yaml quay.io/myorg/mycatalog:v1.0.0
74+
/olm:opm build-semver-index-image catalog-config.yaml quay.io/myorg/mycatalog:v1.0.0 --cacheless
75+
/olm:opm build-semver-index-image catalog-config.yaml quay.io/myorg/mycatalog:v1.0.0 --arch=amd64
76+
/olm:opm build-semver-index-image catalog-config.yaml quay.io/myorg/mycatalog:v1.0.0 --arch=multi
77+
```
78+
79+
### generate-semver-template
80+
Generate a semver template configuration file for building operator catalogs.
81+
82+
**Synopsis:**
83+
```
84+
/olm:opm generate-semver-template <bundle-list> [--output=<file>] [--major=true|false] [--minor=true|false]
85+
```
86+
87+
**Arguments:**
88+
- `$2`: **bundle-list** - Comma-separated list of bundle image references (e.g., `quay.io/org/bundle:v1.0.0,quay.io/org/bundle:v1.0.1`)
89+
- `--output=<file>`: Optional output file path (default: `catalog-semver-config.yaml` in current directory)
90+
- `--major=true|false`: Optional flag to generate major version channels (default: `true`)
91+
- `--minor=true|false`: Optional flag to generate minor version channels (default: `false`)
92+
93+
**Examples:**
94+
```
95+
/olm:opm generate-semver-template quay.io/org/bundle:v1.0.0,quay.io/org/bundle:v1.0.1
96+
/olm:opm generate-semver-template quay.io/org/bundle:v1.0.0,quay.io/org/bundle:v1.0.1 --output=my-catalog.yaml
97+
/olm:opm generate-semver-template quay.io/org/bundle:v1.0.0,quay.io/org/bundle:v1.1.0 --minor=true
98+
```
99+
100+
### list packages
101+
List all operator packages available in a catalog index.
102+
103+
**Synopsis:**
104+
```
105+
/olm:opm list packages <index-ref>
106+
```
107+
108+
**Arguments:**
109+
- `$2`: **list** - Must be "list"
110+
- `$3`: **packages** - Must be "packages"
111+
- `$4`: **index-ref** - Catalog index reference, either:
112+
- Image tag: `quay.io/myorg/mycatalog:v1.0.0`
113+
- Directory path: `./catalog` or `/path/to/catalog`
114+
115+
**Examples:**
116+
```
117+
/olm:opm list packages quay.io/olmqe/nginx8518-index-test:v1
118+
/olm:opm list packages ./catalog
119+
```
120+
121+
### list channels
122+
List channels for operator packages in a catalog index.
123+
124+
**Synopsis:**
125+
```
126+
/olm:opm list channels <index-ref> [package-name]
127+
```
128+
129+
**Arguments:**
130+
- `$2`: **list** - Must be "list"
131+
- `$3`: **channels** - Must be "channels"
132+
- `$4`: **index-ref** - Catalog index reference (image tag or directory path)
133+
- `$5`: **package-name** (Optional) - Name of a specific package to list channels for
134+
135+
**Examples:**
136+
```
137+
/olm:opm list channels quay.io/olmqe/nginx8518-index-test:v1
138+
/olm:opm list channels quay.io/olmqe/nginx8518-index-test:v1 nginx85187
139+
/olm:opm list channels ./catalog
140+
```
141+
142+
### list bundles
143+
List bundles for operator packages in a catalog index.
144+
145+
**Synopsis:**
146+
```
147+
/olm:opm list bundles <index-ref> [package-name]
148+
```
149+
150+
**Arguments:**
151+
- `$2`: **list** - Must be "list"
152+
- `$3`: **bundles** - Must be "bundles"
153+
- `$4`: **index-ref** - Catalog index reference (image tag or directory path)
154+
- `$5`: **package-name** (Optional) - Name of a specific package to list bundles for
155+
156+
**Examples:**
157+
```
158+
/olm:opm list bundles quay.io/olmqe/nginx8518-index-test:v1
159+
/olm:opm list bundles quay.io/olmqe/nginx8518-index-test:v1 nginx85187
160+
/olm:opm list bundles ./catalog
161+
```
162+
163+
## Implementation
164+
165+
### Step 1: Parse Action
166+
- Extract the action from `$1`
167+
- Validate the action is one of: `build-index-image`, `build-semver-index-image`, `generate-semver-template`, `list`
168+
- If invalid action, display error with available actions
169+
170+
### Step 2: Check Prerequisites
171+
Verify required tools are installed:
172+
- Check for `opm`: `which opm`
173+
- If not found, provide installation instructions: https://github.com/operator-framework/operator-registry/releases
174+
- For build actions, also check for `podman`: `which podman`
175+
- If not found, provide installation instructions based on user's platform
176+
177+
### Step 3: Route to Action Handler
178+
Based on the action, call the appropriate implementation:
179+
180+
#### For `build-index-image`:
181+
1. **Parse Arguments and Set Defaults**
182+
- Extract catalog path from `$2`
183+
- Extract index image tag from `$3`
184+
- Parse optional flags: `--cacheless`, `--arch`, `--base-image`, `--builder-image`
185+
- Set defaults: arch=`multi`, base-image=`quay.io/operator-framework/opm:latest`, builder-image=`quay.io/operator-framework/opm:latest`
186+
187+
2. **Verify Catalog Directory**
188+
- Check catalog directory exists: `test -d <catalog-path>`
189+
190+
3. **Validate Catalog**
191+
```bash
192+
opm validate <catalog-path>
193+
```
194+
195+
4. **Generate Dockerfile**
196+
- If cacheless: `opm generate dockerfile <catalog-path> --base-image=scratch`
197+
- If normal: `opm generate dockerfile <catalog-path> -b <builder-image> -i <base-image>`
198+
199+
5. **Determine Build Platform**
200+
- If arch=`multi`: `linux/amd64,linux/arm64,linux/ppc64le,linux/s390x`
201+
- Otherwise: `linux/<arch>`
202+
203+
6. **Create Podman Manifest**
204+
```bash
205+
podman manifest rm <index-image-tag> 2>/dev/null || true
206+
podman manifest create <index-image-tag>
207+
```
208+
209+
7. **Build Image**
210+
```bash
211+
podman build --platform <platform-list> --manifest <index-image-tag> . -f catalog.Dockerfile
212+
```
213+
214+
8. **Push Manifest**
215+
```bash
216+
podman manifest push <index-image-tag>
217+
```
218+
219+
9. **List Bundles in Index**
220+
```bash
221+
opm alpha list bundles <index-image-tag>
222+
```
223+
224+
10. **Display Success Message**
225+
226+
#### For `build-semver-index-image`:
227+
1. **Parse Arguments and Set Defaults**
228+
- Extract semver template file from `$2`
229+
- Extract index image tag from `$3`
230+
- Parse optional flags: `--cacheless`, `--arch`, `--base-image`, `--builder-image`
231+
- Set defaults: arch=`multi`, base-image=`quay.io/operator-framework/opm:latest`, builder-image=`quay.io/operator-framework/opm:latest`
232+
233+
2. **Verify Template File**
234+
- Check file exists: `test -f <semver-template-file>`
235+
236+
3. **Create Catalog and Render Template**
237+
```bash
238+
mkdir -p catalog
239+
opm alpha render-template semver <semver-template-file> -o yaml > catalog/index.yaml
240+
```
241+
242+
4. **Validate Catalog**
243+
```bash
244+
opm validate catalog
245+
```
246+
247+
5. **Generate Dockerfile**
248+
- If cacheless: `opm generate dockerfile catalog --base-image=scratch`
249+
- If normal: `opm generate dockerfile catalog -b <builder-image> -i <base-image>`
250+
251+
6. **Determine Build Platform**
252+
- If arch=`multi`: `linux/amd64,linux/arm64,linux/ppc64le,linux/s390x`
253+
- Otherwise: `linux/<arch>`
254+
255+
7. **Create Podman Manifest**
256+
```bash
257+
podman manifest rm <index-image-tag> 2>/dev/null || true
258+
podman manifest create <index-image-tag>
259+
```
260+
261+
8. **Build Image**
262+
```bash
263+
podman build --platform <platform-list> --manifest <index-image-tag> . -f catalog.Dockerfile
264+
```
265+
266+
9. **Push Manifest**
267+
```bash
268+
podman manifest push <index-image-tag>
269+
```
270+
271+
10. **List Bundles in Index**
272+
```bash
273+
opm alpha list bundles <index-image-tag>
274+
```
275+
276+
11. **Display Success Message**
277+
278+
#### For `generate-semver-template`:
279+
1. **Parse Arguments and Set Defaults**
280+
- Extract bundle list from `$2`
281+
- Parse optional flags: `--output`, `--major`, `--minor`
282+
- Set defaults: output=`catalog-semver-config.yaml`, major=`true`, minor=`false`
283+
284+
2. **Validate Bundle List**
285+
- Split by commas
286+
- Validate each bundle is a valid image reference
287+
288+
3. **Generate YAML Content**
289+
```yaml
290+
Schema: olm.semver
291+
GenerateMajorChannels: <major-value>
292+
GenerateMinorChannels: <minor-value>
293+
Candidate:
294+
Bundles:
295+
- Image: <bundle-1>
296+
- Image: <bundle-2>
297+
```
298+
299+
4. **Write Template File**
300+
- Check if file exists and confirm overwrite if needed
301+
- Write YAML content
302+
303+
5. **Validate Generated File**
304+
- Read back and verify YAML is well-formed
305+
306+
6. **Display Success Message**
307+
- Show file path, bundles included, settings
308+
- Suggest next step: `/olm:opm build-semver-index-image <output-file> <image-tag>`
309+
310+
#### For `list`:
311+
1. **Parse List Type**
312+
- Extract list type from `$2` (must be `packages`, `channels`, or `bundles`)
313+
- If invalid, display error with available types
314+
315+
2. **Parse Index Reference and Optional Package**
316+
- Extract index-ref from `$3`
317+
- Extract optional package-name from `$4` (for channels and bundles)
318+
319+
3. **Determine Reference Type**
320+
- Check if directory: `test -d <index-ref>`
321+
322+
4. **Execute List Command**
323+
- For packages: `opm alpha list packages <index-ref>`
324+
- For channels: `opm alpha list channels <index-ref> [package-name]`
325+
- For bundles: `opm alpha list bundles <index-ref> [package-name]`
326+
327+
5. **Display Results**
328+
- Show the output with appropriate formatting
329+
- Display count of items found
330+
331+
## Return Value
332+
333+
**Format**: Varies by action
334+
335+
- **build-index-image / build-semver-index-image**: Success message with image tag, architectures, and bundle list
336+
- **generate-semver-template**: Success message with file path and configuration details
337+
- **list**: Table or list of catalog contents
338+
339+
On failure, displays:
340+
- Clear error message indicating which step/action failed
341+
- Relevant tool output for debugging
342+
- Suggestions for resolution
343+
344+
## Notes
345+
346+
- Ensure you are authenticated to container registries before building/pushing images (use `podman login`)
347+
- For build operations, the `catalog.Dockerfile` is created in the current working directory
348+
- Multi-architecture builds can be time-consuming
349+
- Cacheless builds result in smaller images and use `scratch` as the base image
350+
- When using `--cacheless`, the `--base-image` and `--builder-image` options are ignored (scratch is always used as base)
351+
- Index references can be either image tags or local directory paths
352+
- Bundle images must be accessible from where you build the catalog
353+
- Image tags should include the full registry hostname (e.g., `quay.io/org/image:tag` not `quay/org/image:tag`)
354+
355+
## Related Commands
356+
357+
- `/olm:install` - Install an operator using OLM
358+
- `/olm:catalog` - Manage catalog sources
359+
- `/olm:debug` - Debug OLM issues

0 commit comments

Comments
 (0)