Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RHOAIENG-15333: chore(ci): create a Python script that reads Workbench image manifests and outputs snippet suited for inclusion in Docs #796

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
153 changes: 153 additions & 0 deletions ci/package_versions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
#!/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"""

ROOT_DIR = pathlib.Path(__file__).parent.parent


@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
"""
Loading