Skip to content

Commit

Permalink
Make c9s variant contain c9s content only, no OCP content
Browse files Browse the repository at this point in the history
This is a first stab at #799, aimed at the c9s variant to start.

In this model, the base (container and disk) images we build in the
pipeline do not contain any OCP-specific details. The compose is made up
purely of RPMs coming out directly from the c9s pungi composes.

Let's go over details of this in bullet form:
1. To emphasize the binding to c9s composes, we change the versioning
   scheme: the version string is now *exactly* the same version as the
   pungi compose from which we've built (well, we do add a `.N` field
   because we want to be able to rebuild multiple times on top of the
   same base pungi compose). It's almost like if our builds are part of
   the c9s pungi composes directly. (And maybe one day they will be...)
   This is implemented using a `versionary` script that queries compose
   info.
2. We no longer include `packages-openshift.yaml`: this has all the OCP
   stuff that we want to do in a layered build instead.
3. We no longer completely rewrite `/etc/os-release`. The host *is*
   image-mode CentOS Stream and e.g. `ID` will now say `centos`.
   However, we do still inject `VARIANT` and `VARIANT_ID` fields to
   note that it's of the CoreOS kind. We should probably actually match
   FCOS here and properly add a CoreOS variant in the `centos-release`
   package.
4. Tests which have to do with the OpenShift layer now have the required
   tag `openshift`. This means that it'll no longer run in the default
   set of kola tests. When building the derived image, we will run just
   those tests using `kola run --tag openshift --oscontainer ...`.

Note that to make this work, OCP itself still needs to actually have
that derived image containing the OCP bits. For now, we will build this
in the pipelines (as a separate artifact that we push to the repos) but
the eventual goal is that we'd split that out of the pipeline and have
it be more like how the rest of OCP is built (using Prow/OSBS/Konflux).

Note also we don't currently build the c9s variant in the pipelines but
this is a long time overdue IMO.
  • Loading branch information
jlebon committed Feb 21, 2024
1 parent ec808e8 commit d1c49aa
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 92 deletions.
105 changes: 13 additions & 92 deletions manifest-c9s.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# Manifest for CentOS Stream CoreOS (SCOS)
# Manifest for CentOS Stream 9 CoreOS Base

rojig:
license: MIT
name: scos
summary: OKD 4
summary: CentOS Stream 9 CoreOS

variables:
osversion: "c9s"
Expand All @@ -12,109 +12,30 @@ variables:
# common to RHEL 9 & C9S variants
include:
- common.yaml
- packages-openshift.yaml

# Starting from here, everything should be specific to SCOS

# CentOS Stream 9 repos + internal repos for now
repos:
- baseos
- appstream
# CentOS Extras Common repo for SIG RPM GPG keys
- extras-common
# CentOS NFV SIG repo for openvswitch
- sig-nfv
# CentOS Cloud SIG repo for cri-o, cri-tools and conmon-rs
- sig-cloud-okd
# Include RHCOS 9 repo for oc, hyperkube
- rhel-9.2-server-ose-4.16

# We include hours/minutes to avoid version number reuse
automatic-version-prefix: "416.9.<date:%Y%m%d%H%M>"
# This ensures we're semver-compatible which OpenShift wants
automatic-version-suffix: "-"
# Keep this is sync with the version in postprocess
mutate-os-release: "4.16"
# Match the format of c9s compose IDs. This field will be driven in the pipeline
# anyway to match exactly the same compose ID we're composing with so the value
# here is purely for developer builds.
automatic-version-prefix: "9-<date:%Y%m%d>.dev"

mutate-os-release: "9"

# Mark the OS as of the CoreOS variant.
postprocess:
- |
#!/usr/bin/env bash
set -xeo pipefail
# Tweak /usr/lib/os-release
grep -v "OSTREE_VERSION" /etc/os-release > /usr/lib/os-release.stream
OCP_RELEASE="4.16"
(
. /etc/os-release
cat > /usr/lib/os-release <<EOF
NAME="${NAME} CoreOS"
ID="scos"
ID_LIKE="rhel fedora"
VERSION="${OSTREE_VERSION}"
VERSION_ID="${OCP_RELEASE}"
VARIANT="CoreOS"
#!/usr/bin/bash
set -euo pipefail
cat >> /usr/lib/os-release <<EOF
VARIANT=CoreOS
VARIANT_ID=coreos
PLATFORM_ID="${PLATFORM_ID}"
PRETTY_NAME="${NAME} CoreOS ${OSTREE_VERSION}"
ANSI_COLOR="${ANSI_COLOR}"
CPE_NAME="${CPE_NAME}::coreos"
HOME_URL="${HOME_URL}"
DOCUMENTATION_URL="https://docs.okd.io/latest/welcome/index.html"
BUG_REPORT_URL="https://access.redhat.com/labs/rhir/"
REDHAT_BUGZILLA_PRODUCT="OpenShift Container Platform"
REDHAT_BUGZILLA_PRODUCT_VERSION="${OCP_RELEASE}"
REDHAT_SUPPORT_PRODUCT="OpenShift Container Platform"
REDHAT_SUPPORT_PRODUCT_VERSION="${OCP_RELEASE}"
OPENSHIFT_VERSION="${OCP_RELEASE}"
OSTREE_VERSION="${OSTREE_VERSION}"
EOF
)
rm -f /etc/os-release
ln -s ../usr/lib/os-release /etc/os-release
# Tweak /etc/system-release, /etc/system-release-cpe & /etc/redhat-release
(
. /etc/os-release
cat > /usr/lib/system-release-cpe <<EOF
${CPE_NAME}
EOF
cat > /usr/lib/system-release <<EOF
${NAME} release ${VERSION_ID}
EOF
rm -f /etc/system-release-cpe /etc/system-release /etc/redhat-release
ln -s /usr/lib/system-release-cpe /etc/system-release-cpe
ln -s /usr/lib/system-release /etc/system-release
ln -s /usr/lib/system-release /etc/redhat-release
)
# Tweak /usr/lib/issue
cat > /usr/lib/issue <<EOF
\S \S{VERSION_ID}
EOF
rm -f /etc/issue /etc/issue.net
ln -s /usr/lib/issue /etc/issue
ln -s /usr/lib/issue /etc/issue.net
# Packages that are only in SCOS and not in RHCOS or that have special
# constraints that do not apply to RHCOS
packages:
# We include the generic release package and tweak the os-release info in a
# post-proces script
- centos-release
# RPM GPG keys for CentOS SIG repos
- centos-release-cloud-common
- centos-release-nfv-common
- centos-release-virt-common

# Packages pinned to specific repos in SCOS 9
repo-packages:
# We always want the kernel from BaseOS
- repo: baseos
packages:
- kernel
- repo: appstream
packages:
# We want the one shipping in C9S, not the equivalently versioned one in RHAOS
- nss-altfiles
# Use the new containers/toolbox
- toolbox
1 change: 1 addition & 0 deletions tests/kola/files/openvswitch-hugetlbfs-groups
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## exclusive: false
## architectures: "x86_64 ppc64le"
## description: Verify openvswitch user is in the hugetlbfs group.
## requiredTag: openshift

set -xeuo pipefail

Expand Down
3 changes: 3 additions & 0 deletions tests/kola/version/rhel-major-version
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ set -xeuo pipefail

variant="$(source /etc/os-release; echo "${ID}")"
case "${variant}" in
"centos")
osver="$(source /etc/os-release; echo "${VERSION_ID}")"
;;
"scos")
osver="$(source /usr/lib/os-release.stream; echo "${VERSION}")"
;;
Expand Down
6 changes: 6 additions & 0 deletions tests/kola/version/rhel-matches-rhcos-build
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## exclusive: false
## description: Verify that the OS version (C9S, RHEL 9.x) matches
## the version stored in /etc/os-release.
## requiredTag: openshift

set -xeuo pipefail

Expand All @@ -11,6 +12,11 @@ set -xeuo pipefail
ocp_version="$(source /etc/os-release; echo "${VERSION}")"
variant="$(source /etc/os-release; echo "${ID}")"
case "${variant}" in
"centos")
# We skip this in the base SCOS case; our package set is pure CentOS and
# the version string matches the compose ID, so this test is invalid.
exit 0
;;
"scos")
# on SCOS, this is just "9"
osver="$(source /usr/lib/os-release.stream; echo "${VERSION_ID}")"
Expand Down
134 changes: 134 additions & 0 deletions versionary
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
#!/usr/bin/python3 -u

# This script requires the yum repos used by our compose to be direct output
# from pungi composes.

import configparser
import dnf
import json
import os
import re
import requests
import subprocess
import sys
import yaml

from urllib.parse import urlparse, urlunparse


def main():
manifest_path = get_manifest_path()
manifest = get_flattened_manifest(manifest_path)
base = get_dnf_base('src/config')
repoids = manifest['repos']

# get base compose URL, verifying at the same time that all the repos point
# into the same pungi compose
compose_url = None
for id in repoids:
repo_compose_url = get_compose_url(base.repos[id])
if compose_url is None:
compose_url = repo_compose_url
else:
if compose_url != repo_compose_url:
raise Exception(f"inconsistent compose URLs detected: {compose_url} vs {repo_compose_url}")

config = configparser.ConfigParser()
config.read_string(requests.get(compose_url + '/.composeinfo').text)

composeid = config['product']['name'].removeprefix(config['product']['short'] + '-')
eprint(f"composeid: {composeid}")

next_iteration = get_next_iteration(composeid)

# XXX: we should verify before leaving that the cached rpmmd repos we have
# are from the compose we found to rule out race conditions between `cosa
# fetch` and `requests.get()` above (e.g. compare the sha256 of repomd.xml)

print(f"{composeid}.{next_iteration}")


def get_compose_url(repo):
assert len(repo.baseurl) == 1
url = urlparse(repo.baseurl[0])
path = url.path.rstrip('/')
components = path.split('/')
assert components[-1] == 'os'
# go up three levels since the structure is e.g. .../compose/<variant>/
# <arch>/os and we want to get to .../compose
return urlunparse(url._replace(path='/'.join(components[:-3])))


def get_dnf_base(basedir):
base = dnf.Base()
base.conf.reposdir = basedir
base.read_all_repos()
return base


def setup_repos(base, treefile):
for repo in base.repos.values():
repo.disable()

eprint("Enabled repos:")
for repo in treefile['repos']:
base.repos[repo].enable()
eprint(f"- {repo}")


def get_next_iteration(composeid):
try:
with open('builds/builds.json') as f:
builds = json.load(f)
except FileNotFoundError:
builds = {'builds': []}

if len(builds['builds']) == 0:
eprint("n: 0 (no previous builds)")
return 0

last_buildid = builds['builds'][0]['id']
last_version = parse_version(last_buildid)
if not last_version:
eprint(f"n: 0 (previous version {last_buildid} does not match scheme)")
return 0

last_composeid, last_iteration = last_version

if composeid != last_composeid:
eprint(f"n: 0 (previous version {last_buildid} compose ID does not match)")
return 0

n = last_iteration + 1
eprint(f"n: {n} (incremented from previous version {last_buildid})")
return n


def parse_version(version):
m = re.match(r'^([0-9]+-[0-9]{8}\.[0-9]+)\.([0-9]+)$', version)
if m is None:
return None
composeid, iteration = m.groups()
return tuple((composeid, int(iteration)))


def get_manifest_path():
if os.path.exists('src/config.json'):
config_json = json.load(open('src/config.json'))
variant = config_json['coreos-assembler.config-variant']
return f'src/config/manifest-{variant}.yaml'
return 'src/config/manifest.yaml'


def get_flattened_manifest(fn):
return yaml.safe_load(
subprocess.check_output(['rpm-ostree', 'compose', 'tree',
'--print-only', fn]))


def eprint(*args):
print(*args, file=sys.stderr)


if __name__ == "__main__":
sys.exit(main())

0 comments on commit d1c49aa

Please sign in to comment.