Skip to content

Commit ed1e7eb

Browse files
razvanclaude
andauthored
fix(olm): support the 26.7.0 chart and registry layout (#129)
SDP 26.7.0 changed how the operator Helm charts reference registries, which broke OLM manifest generation in three ways: * Operator images moved under the "sdp" path on quay.io, so the digest lookup no longer resolved. Introduce QUAY_REPO for the repository prefix. Also add the trailing slash to the tag API URL, which quay now 308-redirects to. * The charts no longer define image.repository in values.yaml; it comes from a per-registry overlay instead. Without one the chart fails to render, and the new IMAGE_REPOSITORY env var (which tells the operator where to pull product images from) has no value. Pass values/quay.io.yaml so bundles reference quay.io throughout. * The product cluster role is now empty unless the OpenShift API is advertised, because its only remaining rule is the securitycontextconstraints grant. Pass --api-versions security.openshift.io/v1 and drop the Python patching of that rule. The charts gate it themselves, and some operators gate more than one cluster role this way (spark has three, opa has two) which the single-role patch silently missed. Also correct the module docstring, which documented a nonexistent --output-dir, and the secret/listener rejection message, which pointed at a deleted script. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent c588672 commit ed1e7eb

1 file changed

Lines changed: 38 additions & 20 deletions

File tree

olm/build-manifests.py

Lines changed: 38 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,22 @@
88
"""
99
(Re)Generate Stackable operator manifests for the Operator Lifecycle Manager (OLM).
1010
11-
The script renders the Helm chart, looks up image digests on
12-
quay.io, and writes a complete OLM bundle under deploy/olm/<version>/.
11+
The script renders the Helm chart, looks up image digests on quay.io, and writes a
12+
complete OLM bundle to <repo-certified-operators>/operators/stackable-<op>/<release>/.
13+
14+
Ensure the operator repository is checked out at the release tag before running this.
1315
1416
Usage:
1517
16-
uv run --script olm/generate-olm.py --version 26.3.0 --repo-operator ~/repo/stackable/airflow-operator --output-dir deploy/olm
18+
uv run --script olm/build-manifests.py \
19+
--release 26.7.0 \
20+
--openshift-versions v4.18-v4.22 \
21+
--repo-operator ~/repo/stackable/airflow-operator \
22+
--repo-certified-operators ~/repo/stackable/openshift-certified-operators
1723
1824
# Or directly with python3 (PyYAML must be installed):
19-
python3 olm/generate-olm.py --version 26.3.0 --repo-operator ~/repo/stackable/airflow-operator --openshift-versions v4.18-v4.21
25+
python3 olm/build-manifests.py --release 26.7.0 --openshift-versions v4.18-v4.22 \
26+
--repo-operator ~/repo/stackable/airflow-operator
2027
2128
Requirements:
2229
- uv (https://docs.astral.sh/uv/) — installs PyYAML automatically
@@ -39,6 +46,11 @@
3946

4047
__version__ = "0.0.1"
4148

49+
# Quay.io repository that hosts the operator images. Since SDP 26.7.0 the images live
50+
# under the "sdp" path, e.g. quay.io/stackable/sdp/hbase-operator.
51+
QUAY_REPO = "stackable/sdp"
52+
53+
4254
class ManifestException(Exception):
4355
pass
4456

@@ -130,7 +142,8 @@ def parse_args(argv: list[str]) -> argparse.Namespace:
130142

131143
if args.op_name in {"secret-operator", "listener-operator"}:
132144
raise ManifestException(
133-
f"Operator '{args.op_name}' is not supported by this script. Use the 'build-manifests.sh' for it."
145+
f"Operator '{args.op_name}' is not supported by this script. "
146+
f"Use 'scripts/generate-olm.py' in the {args.op_name} repository instead."
134147
)
135148

136149
args.op_name = args.repo_operator.name
@@ -413,9 +426,27 @@ def generate_helm_templates(args: argparse.Namespace) -> list[dict]:
413426
helm_values_path = template_path / "values.yaml"
414427
# Path to the custom values for OLM.
415428
olm_values_path = pathlib.Path(__file__).parent / "resources" / "values" / args.repo_operator.name / "values.yaml"
429+
# Since SDP 26.7.0 the charts no longer define image.repository in values.yaml. It is
430+
# supplied by a per-registry overlay instead. OLM bundles must reference quay.io, and
431+
# the overlay also drives the IMAGE_REPOSITORY env var that tells the operator where to
432+
# pull product images from. Without it the chart fails to render.
433+
registry_values_path = template_path / "values" / "quay.io.yaml"
434+
if not registry_values_path.exists():
435+
raise ManifestException(
436+
f"Registry values overlay not found: {registry_values_path}"
437+
)
416438
helm_template_cmd = ["helm", "template", args.op_name,
439+
# Advertise the OpenShift API so that the charts render the
440+
# securitycontextconstraints rules guarded by
441+
# '.Capabilities.APIVersions.Has "security.openshift.io/v1"'.
442+
# Some operators gate more than one cluster role this way
443+
# (spark has three, opa has two), so relying on the chart is both
444+
# more complete and more deterministic than patching a single role
445+
# here.
446+
"--api-versions", "security.openshift.io/v1",
417447
"--values", helm_values_path,
418448
"--values", olm_values_path,
449+
"--values", registry_values_path,
419450
template_path]
420451
try:
421452
logging.debug("start generate_helm_templates")
@@ -440,19 +471,6 @@ def generate_helm_templates(args: argparse.Namespace) -> list[dict]:
440471
except KeyError:
441472
pass
442473

443-
### Patch the product cluster role with the SCC rule
444-
if (
445-
man["kind"] == "ClusterRole"
446-
and man["metadata"]["name"] == f"{args.product}-clusterrole"
447-
):
448-
man["rules"].append(
449-
{
450-
"apiGroups": ["security.openshift.io"],
451-
"resources": ["securitycontextconstraints"],
452-
"resourceNames": ["nonroot-v2"],
453-
"verbs": ["use"],
454-
}
455-
)
456474
### Patch the version label
457475
try:
458476
if (
@@ -490,7 +508,7 @@ def quay_image(images: list[tuple[str, str]]) -> list[dict[str, str]]:
490508
for image, release in images:
491509
release_tag = urllib.parse.urlencode({"specificTag": release})
492510
tag_url = (
493-
f"https://quay.io/api/v1/repository/stackable/{image}/tag?{release_tag}"
511+
f"https://quay.io/api/v1/repository/{QUAY_REPO}/{image}/tag/?{release_tag}"
494512
)
495513
logging.debug(f"Fetching image manifest from {tag_url}")
496514
with urllib.request.urlopen(tag_url) as response:
@@ -517,7 +535,7 @@ def quay_image(images: list[tuple[str, str]]) -> list[dict[str, str]]:
517535
result.append(
518536
{
519537
"name": image,
520-
"image": f"quay.io/stackable/{image}@{manifest_digest[0]}",
538+
"image": f"quay.io/{QUAY_REPO}/{image}@{manifest_digest[0]}",
521539
}
522540
)
523541
logging.debug("finish op_image")

0 commit comments

Comments
 (0)