diff --git a/README.md b/README.md index d2673dd..e57c409 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,64 @@ the organization ``, run: ``` If you push to the users repository, then organiztion is your username. +## info.yaml format + +- `is_versioned`: **bool** (REQUIRED) + + Whether to use package version as a tag for this image + +- `source_packages`: **list of strings** (REQUIRED) + + List of source packages (src.rpm) this image depends on. + If contains jinja2 template syntax, `--package-version` + CLI option must be specified. + +- `version_template`: **string** (OPTIONAL) + + template to apply when construction the tag, + `version` string variable is available in the template + +### examples + + +#### org/k8s/flannel-cni-plugin + +```yaml +is_versioned: true +version_template: v{{ version.rsplit('.', 1) | first }}-flannel{{ version.rsplit('.', 1) | last }} +source_packages: + - cni-plugin-flannel +``` + +```bash +./build.py -i k8s/flannel-cni-plugin +``` + +#### org/k8s/kube-apiserver + +```yaml +is_versioned: true +version_template: v{{ version }} +source_packages: + - kubernetes{{ version }} +``` + +```bash +./build.py -b sisyphus -i k8s/kube-apiserver --package-version '{"k8s/kube-apiserver": "1.31"}' +``` + +#### org/k8s/pause + +```yaml +is_versioned: true +source_packages: + - kubernetes-pause +``` + +```bash +./build.py -i k8s/pause +``` + ## Dependencies On x86_64 machine using p10 branch you need: - `python3-module-tomli` diff --git a/build.py b/build.py index 2e41192..fe86633 100755 --- a/build.py +++ b/build.py @@ -6,25 +6,61 @@ import json import re import subprocess import textwrap +from dataclasses import dataclass from graphlib import TopologicalSorter from pathlib import Path +import requests import tomli +import yaml from jinja2 import Template - ORG_DIR = Path("org") +PKG_VERSIONS: dict | None = None + +@dataclass class Image: - def __init__(self, canonical_name): + canonical_name: str + is_versioned: bool | None + verion_template: str | None + source_packages: list[str] | None + + def __init__(self, canonical_name: str): self.canonical_name = canonical_name self.path = ORG_DIR / canonical_name self.base_name = re.sub("^[^/]+/", "", canonical_name) - def __str__(self): - return (f'Image(canonical_name="{self.canonical_name}", ' - f'path="{self.path}", base_name="{self.base_name}")') + info_file = self.path / "info.yaml" + if not info_file.exists(): + self.is_versioned = None + self.source_packages = None + return + + info: dict = yaml.safe_load(info_file.read_text()) + + if "is_versioned" not in info: + raise RuntimeError( + f"info.yaml for {self.canonical_name} doesn't contain 'is_versioned' key" + ) + + if "source_packages" not in info: + raise RuntimeError( + f"info.yaml for {self.canonical_name} doesn't contain 'source_packages' key" + ) + + self.is_versioned = info["is_versioned"] + self.source_packages = info["source_packages"] + + if self.is_versioned and not self.source_packages: + raise RuntimeError( + f"source_packages for {self.canonical_name} doesn't contain any values" + ) + + self.version_template = None + if "version_template" in info: + self.version_template = info["version_template"] class Tasks: @@ -49,18 +85,67 @@ class Tasks: ] +def api_get_source_package_version(branch: str, package_name: str) -> str: + api_url = "https://rdb.altlinux.org/api/site/package_versions_from_tasks" + params = {"branch": branch, "name": package_name} + response = requests.get(api_url, params) + if response.status_code != 200: + print(response) + raise RuntimeError( + f"failed to retrieve source package version: source package {package_name!r}, branch {branch!r} " + ) + + result = response.json() + + return result["versions"][0]["version"] + + class Tags: - def __init__(self, tags_file, latest): + def __init__(self, tags_file: str | None, latest: str): if tags_file is None: self._tags = None else: - tags_file = Path(tags_file) - self._tags = tomli.loads(tags_file.read_text()) + self._tags = tomli.loads(Path(tags_file).read_text()) self._latest = latest - def tags(self, branch, image: Image): + def tags(self, branch: str, image: Image): if self._tags is None: - tags = [branch] + if image.is_versioned and image.source_packages: + package_name = image.source_packages[0] + + if re.search("{%.*%}", package_name): + package_name = Template(package_name).render(branch=branch).strip() + print(f"{package_name=}") + + if re.search("{{.*}}", package_name): + if PKG_VERSIONS is None: + raise RuntimeError( + f"--package-versions option is not specified, required for {image.canonical_name!r}" + ) + + if image.canonical_name not in PKG_VERSIONS: + raise RuntimeError( + f"--package-versions option does not contain version for image {image.canonical_name!r}" + ) + + if not PKG_VERSIONS[image.canonical_name]: + raise RuntimeError( + f"invalid version for image {image.canonical_name!r}: {PKG_VERSIONS[image.canonical_name]!r}" + ) + + package_name = Template(package_name).render( + version=PKG_VERSIONS[image.canonical_name] + ) + version = api_get_source_package_version(branch, package_name) + + if image.version_template is not None: + version = ( + Template(image.version_template).render(version=version).strip() + ) + + tags = [version] + else: + tags = [branch] else: tags = self._tags[image.canonical_name][branch].copy() if branch == self._latest: @@ -580,6 +665,12 @@ class DockerBuilder: f"--platform={platforms}", ".", ] + + if PKG_VERSIONS is not None and image.canonical_name in PKG_VERSIONS: + build_cmd.insert( + -1, f"--build-arg=PKG_VERSION={PKG_VERSIONS[image.canonical_name]}" + ) + self.run(build_cmd, cwd=image.path) for tag in tags[1:]: @@ -749,6 +840,11 @@ def parse_args(): choices=stages, help="list of stages to skip", ) + parser.add_argument( + "--package-versions", + type=json.loads, + help="json string where key is image name, value is the package version", + ) args = parser.parse_args() args.stages = set(args.stages) - set(args.skip_stages) @@ -760,7 +856,10 @@ def parse_args(): def main(): + global PKG_VERSIONS + args = parse_args() + PKG_VERSIONS = args.package_versions arches = args.arches images_info = ImagesInfo() tags = Tags(args.tags, args.latest) diff --git a/org/k8s/cert-manager-acmesolver/info.yaml b/org/k8s/cert-manager-acmesolver/info.yaml new file mode 100644 index 0000000..4062c23 --- /dev/null +++ b/org/k8s/cert-manager-acmesolver/info.yaml @@ -0,0 +1,6 @@ +--- +is_versioned: true +version_template: v{{ version }} +source_packages: + - cert-manager +... diff --git a/org/k8s/cert-manager-cainjector/info.yaml b/org/k8s/cert-manager-cainjector/info.yaml new file mode 100644 index 0000000..4062c23 --- /dev/null +++ b/org/k8s/cert-manager-cainjector/info.yaml @@ -0,0 +1,6 @@ +--- +is_versioned: true +version_template: v{{ version }} +source_packages: + - cert-manager +... diff --git a/org/k8s/cert-manager-controller/info.yaml b/org/k8s/cert-manager-controller/info.yaml new file mode 100644 index 0000000..4062c23 --- /dev/null +++ b/org/k8s/cert-manager-controller/info.yaml @@ -0,0 +1,6 @@ +--- +is_versioned: true +version_template: v{{ version }} +source_packages: + - cert-manager +... diff --git a/org/k8s/cert-manager-startupapicheck/info.yaml b/org/k8s/cert-manager-startupapicheck/info.yaml new file mode 100644 index 0000000..4062c23 --- /dev/null +++ b/org/k8s/cert-manager-startupapicheck/info.yaml @@ -0,0 +1,6 @@ +--- +is_versioned: true +version_template: v{{ version }} +source_packages: + - cert-manager +... diff --git a/org/k8s/cert-manager-webhook/info.yaml b/org/k8s/cert-manager-webhook/info.yaml new file mode 100644 index 0000000..4062c23 --- /dev/null +++ b/org/k8s/cert-manager-webhook/info.yaml @@ -0,0 +1,6 @@ +--- +is_versioned: true +version_template: v{{ version }} +source_packages: + - cert-manager +... diff --git a/org/k8s/coredns/Dockerfile.template b/org/k8s/coredns/Dockerfile.template index 6c1d529..11e0631 100644 --- a/org/k8s/coredns/Dockerfile.template +++ b/org/k8s/coredns/Dockerfile.template @@ -8,6 +8,13 @@ LABEL org.opencontainers.image.source="https://github.com/coredns/coredns" LABEL org.opencontainers.image.licenses="Apache-2.0" LABEL org.opencontainers.image.vendor="ALT Linux Team" +{% if branch in ["sisyphus", "p11", "c10f2"] %} +ARG PKG_VERSION + +{{ install_packages("coredns${PKG_VERSION}") }} +{% else %} {{ install_packages("coredns") }} +{% endif %} + ENTRYPOINT ["/usr/bin/coredns"] diff --git a/org/k8s/coredns/info.yaml b/org/k8s/coredns/info.yaml new file mode 100644 index 0000000..431ee02 --- /dev/null +++ b/org/k8s/coredns/info.yaml @@ -0,0 +1,11 @@ +--- +is_versioned: true +version_template: v{{ version }} +source_packages: + - > + {% if branch in ["sisyphus", "p11", "c10f2"] %} + {% raw %}coredns{{ version }}{% endraw %} + {% else %} + coredns + {% endif %} +... diff --git a/org/k8s/etcd/info.yaml b/org/k8s/etcd/info.yaml new file mode 100644 index 0000000..2d5c430 --- /dev/null +++ b/org/k8s/etcd/info.yaml @@ -0,0 +1,12 @@ +--- +is_versioned: true +version_template: > + {% set version_patch = version.split(".")[2] | int %} + {% if version_patch < 16 %} + {{ version }}-0 + {% else %} + v{{ version }} + {% endif %} +source_packages: + - etcd +... diff --git a/org/k8s/flannel-cni-plugin/info.yaml b/org/k8s/flannel-cni-plugin/info.yaml new file mode 100644 index 0000000..4036b6c --- /dev/null +++ b/org/k8s/flannel-cni-plugin/info.yaml @@ -0,0 +1,6 @@ +--- +is_versioned: true +version_template: v{{ version.rsplit('.', 1) | first }}-flannel{{ version.rsplit('.', 1) | last }} +source_packages: + - cni-plugin-flannel +... diff --git a/org/k8s/flannel/info.yaml b/org/k8s/flannel/info.yaml new file mode 100644 index 0000000..7e8b75a --- /dev/null +++ b/org/k8s/flannel/info.yaml @@ -0,0 +1,4 @@ +is_versioned: true +version_template: v{{ version }} +source_packages: + - flannel diff --git a/org/k8s/kube-apiserver/Dockerfile.template b/org/k8s/kube-apiserver/Dockerfile.template index aa66fef..005a9b6 100644 --- a/org/k8s/kube-apiserver/Dockerfile.template +++ b/org/k8s/kube-apiserver/Dockerfile.template @@ -2,7 +2,9 @@ FROM {{ registry }}{{ alt_image }}:{{ branch }} MAINTAINER alt-cloud -{{ install_packages("kubernetes-master") }} +ARG PKG_VERSION + +{{ install_packages("kubernetes${PKG_VERSION}-master") }} ENTRYPOINT ["/usr/bin/kube-apiserver"] diff --git a/org/k8s/kube-apiserver/info.yaml b/org/k8s/kube-apiserver/info.yaml new file mode 100644 index 0000000..61b1ec9 --- /dev/null +++ b/org/k8s/kube-apiserver/info.yaml @@ -0,0 +1,6 @@ +--- +is_versioned: true +version_template: v{{ version }} +source_packages: + - kubernetes{{ version }} +... diff --git a/org/k8s/kube-controller-manager/Dockerfile.template b/org/k8s/kube-controller-manager/Dockerfile.template index 9f02488..5acefd4 100644 --- a/org/k8s/kube-controller-manager/Dockerfile.template +++ b/org/k8s/kube-controller-manager/Dockerfile.template @@ -2,7 +2,9 @@ FROM {{ registry }}{{ alt_image }}:{{ branch }} MAINTAINER alt-cloud -{{ install_packages("kubernetes-master") }} +ARG PKG_VERSION + +{{ install_packages("kubernetes${PKG_VERSION}-master") }} ENTRYPOINT ["/usr/bin/kube-controller-manager"] diff --git a/org/k8s/kube-controller-manager/info.yaml b/org/k8s/kube-controller-manager/info.yaml new file mode 100644 index 0000000..61b1ec9 --- /dev/null +++ b/org/k8s/kube-controller-manager/info.yaml @@ -0,0 +1,6 @@ +--- +is_versioned: true +version_template: v{{ version }} +source_packages: + - kubernetes{{ version }} +... diff --git a/org/k8s/kube-proxy/Dockerfile.template b/org/k8s/kube-proxy/Dockerfile.template index b3a0e41..cacbd8f 100644 --- a/org/k8s/kube-proxy/Dockerfile.template +++ b/org/k8s/kube-proxy/Dockerfile.template @@ -2,7 +2,9 @@ FROM {{ registry }}{{ alt_image }}:{{ branch }} MAINTAINER alt-cloud -{{ install_packages("kubernetes-node") }} +ARG PKG_VERSION + +{{ install_packages("kubernetes${PKG_VERSION}-node") }} RUN ln -s /usr/bin/kube-proxy /usr/local/bin/kube-proxy diff --git a/org/k8s/kube-proxy/info.yaml b/org/k8s/kube-proxy/info.yaml new file mode 100644 index 0000000..61b1ec9 --- /dev/null +++ b/org/k8s/kube-proxy/info.yaml @@ -0,0 +1,6 @@ +--- +is_versioned: true +version_template: v{{ version }} +source_packages: + - kubernetes{{ version }} +... diff --git a/org/k8s/kube-scheduler/Dockerfile.template b/org/k8s/kube-scheduler/Dockerfile.template index d3fae72..a5bf431 100644 --- a/org/k8s/kube-scheduler/Dockerfile.template +++ b/org/k8s/kube-scheduler/Dockerfile.template @@ -2,7 +2,9 @@ FROM {{ registry }}{{ alt_image }}:{{ branch }} MAINTAINER alt-cloud -{{ install_packages("kubernetes-master") }} +ARG PKG_VERSION + +{{ install_packages("kubernetes${PKG_VERSION}-master") }} ENTRYPOINT ["/usr/bin/kube-scheduler"] diff --git a/org/k8s/kube-scheduler/info.yaml b/org/k8s/kube-scheduler/info.yaml new file mode 100644 index 0000000..61b1ec9 --- /dev/null +++ b/org/k8s/kube-scheduler/info.yaml @@ -0,0 +1,6 @@ +--- +is_versioned: true +version_template: v{{ version }} +source_packages: + - kubernetes{{ version }} +... diff --git a/org/k8s/kubelet/info.yaml b/org/k8s/kubelet/info.yaml new file mode 100644 index 0000000..61b1ec9 --- /dev/null +++ b/org/k8s/kubelet/info.yaml @@ -0,0 +1,6 @@ +--- +is_versioned: true +version_template: v{{ version }} +source_packages: + - kubernetes{{ version }} +... diff --git a/org/k8s/pause/info.yaml b/org/k8s/pause/info.yaml new file mode 100644 index 0000000..b676a6f --- /dev/null +++ b/org/k8s/pause/info.yaml @@ -0,0 +1,5 @@ +--- +is_versioned: true +source_packages: + - kubernetes-pause +... diff --git a/org/k8s/trivy-node-collector/info.yaml b/org/k8s/trivy-node-collector/info.yaml new file mode 100644 index 0000000..791a0ee --- /dev/null +++ b/org/k8s/trivy-node-collector/info.yaml @@ -0,0 +1,5 @@ +--- +is_versioned: true +source_packages: + - k8s-trivy-node-collector +...