-
Notifications
You must be signed in to change notification settings - Fork 70
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
RHOAIENG-15333: chore(ci): create a Python script that reads Workbenc…
…h image manifests and outputs snippet suited for inclusion in Docs
- Loading branch information
Showing
2 changed files
with
226 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
#!/usr/bin/env python | ||
|
||
from __future__ import annotations | ||
|
||
import dataclasses | ||
import glob | ||
import io | ||
import json | ||
import pathlib | ||
import typing | ||
import unittest | ||
|
||
import yaml | ||
|
||
import package_versions_selftestdata | ||
|
||
"""Generates the workbench software listings for https://access.redhat.com/articles/rhoai-supported-configs | ||
using the Markdown variant described at https://access.redhat.com/articles/7056942""" | ||
|
||
""" | ||
TODO: | ||
* separate reading data and printing output | ||
so that output can be properly sorted (by opendatahub.io/notebook-image-order probably) | ||
* don't repeat image name when printing multiple tags for it | ||
* run this in red-hat-data-services repo so we also have (or not have) Habana image | ||
* diff it with what's in the knowledge base now, to check if outputs match | ||
""" | ||
|
||
ROOT_DIR = pathlib.Path(__file__).parent.parent | ||
|
||
|
||
# unused for now | ||
@dataclasses.dataclass | ||
class Manifest: | ||
_data: any | ||
|
||
@property | ||
def name(self) -> str: | ||
return self._data['metadata']['annotations']['opendatahub.io/notebook-image-name'] | ||
|
||
@property | ||
def order(self) -> int: | ||
return int(self._data['metadata']['annotations']['opendatahub.io/notebook-image-order']) | ||
|
||
@property | ||
def tags(self) -> list[Tag]: | ||
return [Tag(tag) for tag in self._data['spec']['tags']] | ||
|
||
|
||
@dataclasses.dataclass() | ||
class Tag: | ||
_data: any | ||
|
||
@property | ||
def name(self) -> str: | ||
return self._data['name'] | ||
|
||
@property | ||
def recommended(self) -> bool: | ||
if 'opendatahub.io/workbench-image-recommended' not in self._data['annotations']: | ||
return False | ||
return self._data['annotations']['opendatahub.io/workbench-image-recommended'] == 'true' | ||
|
||
@property | ||
def outdated(self) -> bool: | ||
if 'opendatahub.io/image-tag-outdated' not in self._data['annotations']: | ||
return False | ||
return self._data['annotations']['opendatahub.io/image-tag-outdated'] == 'true' | ||
|
||
@property | ||
def sw_general(self) -> list[typing.TypedDict("Software", {"name": str, "version": str})]: | ||
return json.loads(self._data['annotations']['opendatahub.io/notebook-software']) | ||
|
||
@property | ||
def sw_python(self) -> list[typing.TypedDict("Software", {"name": str, "version": str})]: | ||
return json.loads(self._data['annotations']['opendatahub.io/notebook-python-dependencies']) | ||
|
||
|
||
def main(): | ||
pathname = 'manifests/base/*.yaml' | ||
# pathname = 'manifests/overlays/additional/*.yaml' | ||
imagestreams: list[Manifest] = [] | ||
for fn in glob.glob(pathname, root_dir=ROOT_DIR): | ||
# there may be more than one yaml document in a file (e.g. rstudio buildconfigs) | ||
with (open(ROOT_DIR / fn, 'rt') as fp): | ||
for data in yaml.safe_load_all(fp): | ||
if 'kind' not in data or data['kind'] != 'ImageStream': | ||
continue | ||
if 'labels' not in data['metadata']: | ||
continue | ||
if ('opendatahub.io/notebook-image' not in data['metadata']['labels'] or | ||
data['metadata']['labels']['opendatahub.io/notebook-image'] != 'true'): | ||
continue | ||
imagestream = Manifest(data) | ||
imagestreams.append(imagestream) | ||
|
||
print('Image name | Image version | Preinstalled packages') | ||
print('--------- | ---------') | ||
|
||
# for imagestream in sorted(imagestreams, key=lambda imagestream: imagestream.order): | ||
for imagestream in sorted(imagestreams, key=lambda imagestream: imagestream.name): | ||
name = imagestream.name | ||
|
||
prev_tag = None | ||
for tag in imagestream.tags: | ||
if tag.outdated: | ||
continue | ||
|
||
tag_name = tag.name | ||
recommended = tag.recommended | ||
|
||
sw_general = tag.sw_general | ||
sw_python = tag.sw_python | ||
|
||
software: list[str] = [] | ||
for item in sw_general: | ||
sw_name: str | ||
sw_version: str | ||
sw_name, sw_version = item['name'], item['version'] | ||
sw_version = sw_version.lstrip("v") | ||
software.append(f"{sw_name} {sw_version}") | ||
for item in sw_python: | ||
sw_name: str | ||
sw_version: str | ||
sw_name, sw_version = item['name'], item['version'] | ||
sw_version = sw_version.lstrip("v") | ||
software.append(f"{sw_name}: {sw_version}") | ||
|
||
maybe_techpreview = "" if name not in ('code-server',) else " (Technology Preview)" | ||
maybe_recommended = "" if not recommended or len(imagestream.tags) == 1 else ' (Recommended)' | ||
if not prev_tag: | ||
print(f'{name}{maybe_techpreview} | {tag_name}{maybe_recommended} | {', '.join(software)}') | ||
else: | ||
print(f'| {tag_name}{maybe_recommended} | {', '.join(software)}') | ||
|
||
prev_tag = tag | ||
|
||
|
||
class TestManifest(unittest.TestCase): | ||
_data = yaml.safe_load(io.StringIO(package_versions_selftestdata.imagestream)) | ||
manifest = Manifest(_data) | ||
|
||
def test_name(self): | ||
assert self.manifest.name == "Minimal Python" | ||
|
||
def test_order(self): | ||
assert self.manifest.order == 1 | ||
|
||
def test_tag_name(self): | ||
assert self.manifest.tags[0].name == "2024.2" | ||
|
||
def test_tag_recommended(self): | ||
assert self.manifest.tags[0].recommended is True | ||
|
||
def test_tag_sw_general(self): | ||
assert self.manifest.tags[0].sw_general == [{'name': 'Python', 'version': 'v3.11'}] | ||
|
||
def test_tag_sw_python(self): | ||
assert self.manifest.tags[0].sw_python == [{'name': 'JupyterLab', 'version': '4.2'}] | ||
|
||
|
||
if __name__ == '__main__': | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
imagestream = """ | ||
--- | ||
apiVersion: image.openshift.io/v1 | ||
kind: ImageStream | ||
metadata: | ||
labels: | ||
opendatahub.io/notebook-image: "true" | ||
annotations: | ||
opendatahub.io/notebook-image-url: "https://github.com//opendatahub-io/notebooks/tree/main/jupyter/minimal" | ||
opendatahub.io/notebook-image-name: "Minimal Python" | ||
opendatahub.io/notebook-image-desc: "Jupyter notebook image with minimal dependency set to start experimenting with Jupyter environment." | ||
opendatahub.io/notebook-image-order: "1" | ||
name: jupyter-minimal-notebook | ||
spec: | ||
lookupPolicy: | ||
local: true | ||
tags: | ||
# N Version of the image | ||
- annotations: | ||
# language=json | ||
opendatahub.io/notebook-software: | | ||
[ | ||
{"name": "Python", "version": "v3.11"} | ||
] | ||
# language=json | ||
opendatahub.io/notebook-python-dependencies: | | ||
[ | ||
{"name": "JupyterLab","version": "4.2"} | ||
] | ||
openshift.io/imported-from: quay.io/opendatahub/workbench-images | ||
opendatahub.io/workbench-image-recommended: 'true' | ||
opendatahub.io/default-image: "true" | ||
opendatahub.io/notebook-build-commit: $(odh-minimal-notebook-image-commit-n) | ||
from: | ||
kind: DockerImage | ||
name: $(odh-minimal-notebook-image-n) | ||
name: "2024.2" | ||
referencePolicy: | ||
type: Source | ||
# N Version of the image | ||
- annotations: | ||
# language=json | ||
opendatahub.io/notebook-software: | | ||
[ | ||
{"name": "Python", "version": "v3.9"} | ||
] | ||
# language=json | ||
opendatahub.io/notebook-python-dependencies: | | ||
[ | ||
{"name": "JupyterLab","version": "3.6"}, | ||
{"name": "Notebook","version": "6.5"} | ||
] | ||
openshift.io/imported-from: quay.io/opendatahub/workbench-images | ||
opendatahub.io/workbench-image-recommended: 'false' | ||
opendatahub.io/default-image: "true" | ||
opendatahub.io/notebook-build-commit: $(odh-minimal-notebook-image-commit-n-1) | ||
from: | ||
kind: DockerImage | ||
name: $(odh-minimal-notebook-image-n-1) | ||
name: "2024.1" | ||
referencePolicy: | ||
type: Source | ||
""" |