Skip to content

Commit

Permalink
RHOAIENG-15333: chore(ci): create a Python script that reads Workbenc…
Browse files Browse the repository at this point in the history
…h image manifests and outputs snippet suited for inclusion in Docs
  • Loading branch information
jiridanek committed Dec 5, 2024
1 parent 3f95611 commit 815c6c7
Show file tree
Hide file tree
Showing 2 changed files with 226 additions and 0 deletions.
163 changes: 163 additions & 0 deletions ci/package_versions.py
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()
63 changes: 63 additions & 0 deletions ci/package_versions_selftestdata.py
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
"""

0 comments on commit 815c6c7

Please sign in to comment.