Skip to content

Commit

Permalink
Containerfile: new file
Browse files Browse the repository at this point in the history
This Containerfile allows us to build the OpenShift node image on top
of the base RHCOS/SCOS image (i.e. built from the `c9s` or `rhel-9.4`
image).

Currently, the resulting image is at parity with the base image you'd
get from building the `okd-c9s` or `ocp-rhel-9.4` variant. In the
future, those variants will go away and this will become the only way to
build the node image.

Part of: openshift#799
  • Loading branch information
jlebon committed May 15, 2024
1 parent bf7cdbf commit 7cb5173
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 0 deletions.
33 changes: 33 additions & 0 deletions Containerfile
Original file line number Diff line number Diff line change
@@ -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
75 changes: 75 additions & 0 deletions scripts/apply-manifest
Original file line number Diff line number Diff line change
@@ -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)

0 comments on commit 7cb5173

Please sign in to comment.