Skip to content

Commit 093b360

Browse files
committed
Add helper classes and CLI tool to work with catalog image
The set of classes is introduced that helps with catalog image parsing. The classes automatically parse the catalog using 'opm render' command and splits it into logical sub-classes that represents Catalog, Bundle, Operator package, Channel. The commit also introduces a CLI tool that simplifies working with Catalog images locally and allows user to browse through catalog content in terminal using human readable console output. JIRA: ISV-5279 Signed-off-by: Ales Raszka <araszka@redhat.com>
1 parent c7b6080 commit 093b360

File tree

17 files changed

+1719
-3
lines changed

17 files changed

+1719
-3
lines changed

docs/catalog_image_browser.md

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
# Catalog image browser
2+
Working with catalog images locally might be a tricky task since it requires a lot of manual work.
3+
To make it easier for maintainers and contributors, we have created a simple catalog image
4+
browser CLI tool that allows you to browse and search for images in the catalog locally
5+
in your terminal.
6+
7+
## Installation
8+
To install the catalog browser, you will need a Python 3.10+ environment.
9+
10+
Then, you can install the tool using pip:
11+
12+
```bash
13+
$ pip install git+https://github.com/redhat-openshift-ecosystem/operator-pipelines.git
14+
```
15+
16+
Once installed you can run the tool using the following command:
17+
18+
```bash
19+
$ catalog-browser --help
20+
21+
usage: catalog-browser [-h] [--image IMAGE] [--rendered RENDERED] {list,show} ...
22+
23+
Browse and query index image content.
24+
25+
positional arguments:
26+
{list,show} Commands
27+
list List content in the index image.
28+
show Show details of specific content.
29+
30+
options:
31+
-h, --help show this help message and exit
32+
--image IMAGE Path to the index image.
33+
--rendered RENDERED Path to the rendered index image content.
34+
35+
```
36+
37+
## Usage
38+
The browser requires one of 2 argument inputs: `--image` or `--rendered`. Using `--image` argument
39+
the tool will pull the image and extract the content to a temporary directory. Based on catalog image
40+
size the extraction might take a while. You can also render a catalog
41+
in advance using `opm render` and then using `--rendered` argument to browse the content.
42+
43+
```bash
44+
$ catalog-browser --image registry.redhat.io/redhat/community-operator-index:v4.16 list packages
45+
46+
# or
47+
$ opm render -o yaml registry.redhat.io/redhat/community-operator-index:v4.16 > /tmp/v.4.16.yaml
48+
49+
$ catalog-browser --rendered /tmp/v.4.16.yaml list bundles
50+
```
51+
52+
The browser supports 2 commands: `list` and `show`.
53+
54+
### List
55+
The `list` command will list all packages, bundles or channels
56+
```bash
57+
$ catalog-browser --image registry.redhat.io/redhat/community-operator-index:v4.16 list packages
58+
3scale-community-operator
59+
ack-acm-controller
60+
ack-acmpca-controller
61+
ack-apigateway-controller
62+
ack-apigatewayv2-controller
63+
ack-applicationautoscaling-controller
64+
ack-athena-controller
65+
...
66+
```
67+
68+
```bash
69+
$ catalog-browser --rendered /tmp/v.4.16.yaml list bundles
70+
3scale-community-operator.v0.10.1
71+
3scale-community-operator.v0.8.2
72+
3scale-community-operator.v0.9.0
73+
ack-acm-controller.v0.0.1
74+
ack-acm-controller.v0.0.10
75+
ack-acm-controller.v0.0.12
76+
ack-acm-controller.v0.0.16
77+
ack-acm-controller.v0.0.17
78+
ack-acm-controller.v0.0.18
79+
...
80+
```
81+
82+
### Show
83+
The `show` command will show details of a specific package, bundle or channel in
84+
human readable format.
85+
86+
To show details of a package:
87+
```bash
88+
$ catalog-browser --rendered /tmp/v.4.16.yaml show package tempo-operator
89+
Package: tempo-operator
90+
Channels:
91+
- tempo-operator/alpha
92+
Bundles:
93+
- tempo-operator.v0.1.0
94+
- tempo-operator.v0.10.0
95+
- tempo-operator.v0.11.0
96+
- tempo-operator.v0.11.1
97+
- tempo-operator.v0.12.0
98+
- tempo-operator.v0.13.0
99+
- tempo-operator.v0.14.0
100+
- tempo-operator.v0.14.1
101+
- tempo-operator.v0.14.2
102+
- tempo-operator.v0.2.0
103+
- tempo-operator.v0.3.0
104+
- tempo-operator.v0.4.0
105+
- tempo-operator.v0.5.0
106+
- tempo-operator.v0.6.0
107+
- tempo-operator.v0.7.0
108+
- tempo-operator.v0.8.0
109+
- tempo-operator.v0.9.0
110+
```
111+
112+
To show details of a bundle:
113+
```bash
114+
$ catalog-browser --rendered /tmp/v.4.16.yaml show bundle snyk-operator.v1.90.2
115+
Bundle: snyk-operator.v1.90.2
116+
Package: snyk-operator
117+
Image: quay.io/openshift-community-operators/snyk-operator@sha256:daf143ff1e9fbcf9bbbb350f8aab8593a1a35f693b0118c06a6b84c89a474397
118+
Channels:
119+
- snyk-operator/stable
120+
```

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ nav:
2222
- "OKD/OpenShift Catalogs criteria and options": "users/packaging-required-criteria-ocp.md"
2323
- "Admin":
2424
- "Admin guide": "pipeline-admin-guide.md"
25+
- "Catalog image browser": "catalog_image_browser.md"
2526
theme:
2627
name: material
2728
features:
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
"""
2+
This package contains the code for the operator-catalog image.
3+
"""
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
"""Module representing a bundle in the catalog."""
2+
3+
from typing import Any
4+
5+
6+
class CatalogBundle:
7+
"""
8+
A class representing a bundle in the catalog.
9+
"""
10+
11+
def __init__(self, definition: dict[str, Any], catalog: Any):
12+
self.definition = definition
13+
self.catalog = catalog
14+
15+
@property
16+
def name(self) -> str:
17+
"""
18+
A bundle name property.
19+
20+
Returns:
21+
str: A bundle name.
22+
"""
23+
return self.definition.get("name", "") or ""
24+
25+
@property
26+
def package_name(self) -> str:
27+
"""
28+
A package name property.
29+
30+
Returns:
31+
str: A name of a bundle package.
32+
"""
33+
return self.definition.get("package", "") or ""
34+
35+
@property
36+
def image(self) -> str:
37+
"""
38+
A bundle image property.
39+
40+
Returns:
41+
str: A bundle image pull spec as defined in the catalog.
42+
"""
43+
return self.definition.get("image", "") or ""
44+
45+
def __str__(self) -> str:
46+
"""
47+
String representation of a bundle.
48+
49+
Returns:
50+
str: A name of a bundle.
51+
"""
52+
return self.name
53+
54+
def __repr__(self) -> str:
55+
"""
56+
A representation of a bundle.
57+
58+
Returns:
59+
str: A representation of a bundle class.
60+
"""
61+
return f"CatalogBundle({self.name})"
62+
63+
def get_channels(self) -> list[Any]:
64+
"""
65+
Get all channels for a bundle.
66+
67+
Returns:
68+
list: A list of channels where the bundle is available.
69+
"""
70+
channels = []
71+
for channel in self.catalog.get_all_channels():
72+
if channel.package_name == self.package_name:
73+
channels.append(channel)
74+
return channels
75+
76+
def print(self) -> None:
77+
"""
78+
Print details of a bundle in a formatted way.
79+
"""
80+
print(f"Bundle: {self}")
81+
print(f"Package: {self.catalog.get_package(self.package_name)}")
82+
print(f"Image: {self.image}")
83+
84+
print("Channels:")
85+
for channel in self.get_channels():
86+
print(f" - {channel}")

0 commit comments

Comments
 (0)