diff --git a/Containerfile b/Containerfile new file mode 100644 index 00000000..a514c9ea --- /dev/null +++ b/Containerfile @@ -0,0 +1,33 @@ +# This builds the final OCP node image on top of the base RHCOS image. The +# latter may be RHEL or CentOS Stream-based. This is currently only buildable +# using podman/buildah as it uses some mounting options only available there. +# +# To build this, you will want to pass `--security-opt=label=disable` to avoid +# having to relabel the context directory. Any repos found in `/run/yum.repos.d` +# will be imported into `/etc/yum.repos.d/` and then removed in the same step (so +# as to not end up in the final image). +# +# Use `--from` to override the base RHCOS image. E.g.: +# +# podman build --from quay.io/openshift-release-dev/ocp-v4.0-art-dev:rhel-coreos-base-9.4 ... +# +# Or to use a locally built OCI archive: +# +# podman build --from oci-archive:builds/latest/x86_64/scos-9-20240416.dev.0-ostree.x86_64.ociarchive ... + +# If consuming from repos hosted within the RH network, you'll want to mount in +# certs too: +# +# podman build -v /etc/pki/ca-trust:/etc/pki-ca-trust:ro ... +# +# Example invocation: +# +# podman build --from oci-archive:$(ls builds/latest/x86_64/*.ociarchive) \ +# -v rhel-9.4.repo:/run/yum.repos.d/rhel-9.4.repo:ro \ +# -v /etc/pki/ca-trust:/etc/pki/ca-trust:ro \ +# --security-opt label=disable -t localhost/openshift-node-c9s \ +# src/config + +FROM quay.io/openshift-release-dev/ocp-v4.0-art-dev:rhel-coreos-base-c9s +RUN --mount=type=bind,target=/run/src /run/src/scripts/apply-manifest /run/src/packages-openshift.yaml && \ + ostree container commit diff --git a/scripts/apply-manifest b/scripts/apply-manifest new file mode 100755 index 00000000..ced24170 --- /dev/null +++ b/scripts/apply-manifest @@ -0,0 +1,75 @@ +#!/usr/bin/python3 -u + +# This is a hacky temporary script to apply an rpm-ostree manifest as part of a +# derived container build. It's only required because we're in this transitional +# state where some streams use the old way, and others use layering. Once all +# streams use layering, we could stop using manifests for the layered bits. (An +# obvious question here is whether we should keep extending the `rpm-ostree ex +# rebuild` stuff to keep using manifests even in a layered build. Though likely +# similar functionality will live in dnf instead.) + +# Note this only supports the subset of the manifest spec actually used in +# `packages-openshift.yaml`. + +import os +import shutil +import subprocess +import sys +import yaml + + +def runcmd(args): + print("Running:", ' '.join(args)) + subprocess.check_call(args) + + +manifest_file = sys.argv[1] +manifest_dir = os.path.dirname(manifest_file) + +with open(manifest_file) as f: + manifest = yaml.safe_load(f) + +if len(manifest.get('packages', [])): + + packages = [] + for pkg in manifest['packages']: + packages += pkg.split() + rpmostree_install = ['rpm-ostree', 'install', '-y'] + packages + + # XXX: temporary hack for cri-o, which wants to create dirs under /opt + # https://github.com/CentOS/centos-bootc/issues/393 + if 'cri-o' in packages: + os.makedirs("/var/opt", exist_ok=True) + + # inject mounted-in repo files + extra_repos_dir = '/run/yum.repos.d' + copied_repo_files = [] + if os.path.isdir(extra_repos_dir): + for file in os.listdir(extra_repos_dir): + src_path = os.path.join(extra_repos_dir, file) + if not os.path.isfile(src_path): + continue + if not file.endswith(".repo"): + continue + dest_path = os.path.join('/etc/yum.repos.d', file) + if os.path.exists(dest_path): + raise Exception(f"Repo file {dest_path} already exists") + print(f"Copying repo file {file} to /etc/yum.repos.d/") + shutil.copy(src_path, dest_path) + copied_repo_files += [dest_path] + + runcmd(rpmostree_install) + + # delete the repo files we injected + for repo in copied_repo_files: + os.unlink(repo) + + +if len(manifest.get('postprocess', [])): + for i, script in enumerate(manifest['postprocess']): + name = f"/tmp/postprocess-script-{i}" + with open(name, 'w') as f: + f.write(script) + os.chmod(name, 0o755) + runcmd([name]) + os.unlink(name)