Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .bazelignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ deploy
docs
fern
infra
# infra/cassandra is a nested, self-contained Bazel module (its own
# MODULE.bazel + rules_oci image graph, built via `cd infra/cassandra &&
# bazel build //:image_index`). Listed explicitly so the intent survives if
# the broad `infra` entry above is ever narrowed; keeps the root workspace
# from trying to load the nested module. Mirrors the function-autoscaler /
# stargate nested-module pattern.
infra/cassandra
migrations
tools

Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/bazel.yml
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@ jobs:
worker-utils|src/compute-plane-services/worker-utils|false
function-autoscaler|src/control-plane-services/function-autoscaler|false
helm-reval|src/control-plane-services/helm-reval|false
stargate|src/libraries/rust/stargate|false'
stargate|src/libraries/rust/stargate|false
cassandra|infra/cassandra|false'
# Paths that affect the root-module workspace build (native
# root subtrees, Go and Java, plus the shared Bazel scaffold).
ROOT_GLOBS=(MODULE.bazel .bazelrc .bazelversion BUILD.bazel rules/ platforms/ tools/ ci/ src/clis/ src/libraries/ .github/bazel-root-test-quarantine.txt)
Expand Down
40 changes: 40 additions & 0 deletions infra/cassandra/.bazelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# ============================================================================
# Bazel configuration for the NVCF Cassandra runtime image (image assembly
# only; no language toolchain). Tracks the Phase B OCI scaffold used by the
# stargate / function-autoscaler modules.
# ============================================================================

common --enable_bzlmod
common --enable_platform_specific_config
build --incompatible_strict_action_env

test --test_output=errors

# Workspace status (build stamping). Feeds STABLE_VERSION / STABLE_GIT_COMMIT
# / STABLE_OCI_TAG into the stamped remote tags on the nvidia-internal push
# targets.
build --workspace_status_command=tools/workspace_status.sh

# CI profile.
build:ci --jobs=16

# Release profile. The nvcf-internal bazel release backend builds the image
# with `--config=release` (uniform across services). This image is pure
# assembly (no compiled targets), so opt is effectively a no-op here; the
# config exists so the shared release script runs unmodified.
build:release -c opt
1 change: 1 addition & 0 deletions infra/cassandra/.bazelversion
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
9.1.1
7 changes: 7 additions & 0 deletions infra/cassandra/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

# Bazel (nested module). Convenience symlinks + local caches/overrides.
bazel-*
.bazel-cache/
user.bazelrc
39 changes: 39 additions & 0 deletions infra/cassandra/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,45 @@ docker buildx build --platform linux/amd64,linux/arm64 -t <ref> infra/cassandra
The `--platform=$BUILDPLATFORM` on the yq stage is intentional: it lets yq
cross-download on the host arch without QEMU.

## Bazel image (rules_oci)

This subtree is also a self-contained Bazel module that builds the same image
via `rules_oci`, so it ships and releases like every other NVCF image (no
buildah). It is a nested module: the umbrella ignores it (root `.bazelignore`
lists `infra/cassandra`), so run Bazel from this directory.

```sh
cd infra/cassandra

# Public multi-arch image (amd64 + arm64), OSS-safe (no exporter jar).
bazel build //:image_index # or //:cassandra (non-manual alias)

# yq exec-bit guard.
bazel test //:yq_exec_bit_test
```

Translation of the Dockerfile:
- `FROM cassandra:5.0.8` -> `oci.pull` of the Docker Hub manifest-list digest
in `MODULE.bazel`. The digest is authoritative for the built image; the
Dockerfile tag is a transitional mirror for manual/dev builds. To bump
Cassandra, change these together: (1) the `oci.pull` digest in `MODULE.bazel`
(re-resolve the new tag's multi-arch manifest-list digest), (2) the
`# cassandra-version:` marker beside it, and (3) the Dockerfile
`FROM cassandra:<new>` tag. `cassandra_version_consistency_test` fails the
build if the Dockerfile tag and the marker disagree.
- pinned `yq` -> `http_file` per arch in `rules/repos.bzl` (same version +
sha256s as the Dockerfile), packaged at `/usr/local/bin/yq`.
- `scripts/cassandra-env.sh` -> `pkg_tar` layer over `/etc/cassandra/`.
- `--add-opens` JVM flags -> `JVM_EXTRA_OPTS` env, shared as `JVM_ADD_OPENS`
in `rules/oci/defs.bzl`.

The exporter agent and NGC push destinations are internal-only and do not
live in this repo. The private release repo (nvcf-internal) owns the exporter
jar and a `nvidia-internal/` overlay package; at release time it injects that
overlay into this module (reusing the public `//:yq_layer` and `//:env_layer`
targets), adds the exporter layer plus the `-javaagent` flag, and pushes the
with-exporter image. Nothing exporter-related is declared in this OSS tree.

## Pairs with

- Helm chart `deploy/helm/cassandra` deploys this image; its config init
Expand Down
133 changes: 133 additions & 0 deletions infra/cassandra/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

# Public, OSS-safe Cassandra runtime image (Bazel port of the Dockerfile,
# minus the metrics exporter, which is internal-only). This target builds on
# the NVIDIA/nvcf GitHub mirror. The with-exporter image is produced by the
# private release repo (nvcf-internal), which injects a nvidia-internal/
# overlay package into this module at build time and reuses the public
# layers below; that overlay and its jar never live in this repo.

load("@rules_pkg//pkg:mappings.bzl", "pkg_attributes", "pkg_files", "strip_prefix")
load("@rules_pkg//pkg:tar.bzl", "pkg_tar")
load("@rules_shell//shell:sh_test.bzl", "sh_test")
load("//rules/oci:defs.bzl", "JVM_ADD_OPENS", "create_oci_image")

exports_files([
"scripts/cassandra-env.sh",
# Referenced by cassandra_version_consistency_test as test data.
"MODULE.bazel",
"Dockerfile",
])

# ----------------------------------------------------------------------------
# yq layer: the pinned static binary at /usr/local/bin/yq. Per-arch selection
# resolves under the image's platform transition, so the arm64 image gets the
# arm64 yq and the amd64 image the amd64 yq. Mode 0755 (the chart's config
# init container execs it). Dockerfile parity: `COPY --from=yq-downloader`.
# ----------------------------------------------------------------------------
pkg_files(
name = "yq_files",
srcs = select({
"@platforms//cpu:arm64": ["@yq_linux_arm64//file"],
"@platforms//cpu:x86_64": ["@yq_linux_amd64//file"],
}),
attributes = pkg_attributes(mode = "0755"),
prefix = "/usr/local/bin",
strip_prefix = strip_prefix.files_only(),
)

pkg_tar(
name = "yq_layer",
srcs = [":yq_files"],
# Reused by the nvidia-internal with-exporter variant.
visibility = ["//visibility:public"],
)

# ----------------------------------------------------------------------------
# cassandra-env.sh layer: overwrites the base image's
# /etc/cassandra/cassandra-env.sh with the NCP rack-from-pod variant. Sourced
# (not executed) by /opt/cassandra/bin/cassandra, so mode 0644 matches the
# base. Dockerfile parity: `COPY scripts/cassandra-env.sh`.
# ----------------------------------------------------------------------------
pkg_files(
name = "cassandra_env_files",
srcs = ["scripts/cassandra-env.sh"],
attributes = pkg_attributes(mode = "0644"),
prefix = "/etc/cassandra",
strip_prefix = strip_prefix.files_only(),
)

pkg_tar(
name = "env_layer",
srcs = [":cassandra_env_files"],
visibility = ["//visibility:public"],
)

# ----------------------------------------------------------------------------
# The exporter agent reflects into JDK-internal com.sun.jmx classes; on the
# JDK 17 runtime shipped in the official image those packages are not open to
# unnamed modules by default. These --add-opens are harmless when no agent is
# wired in, so they stay unconditional (matches the Dockerfile). The public
# image sets NO -javaagent (no exporter jar); the with-exporter variant in
# nvidia-internal/ prepends it. JVM_ADD_OPENS is shared from defs.bzl.
# ----------------------------------------------------------------------------
create_oci_image(
name = "image",
base = "@cassandra_base",
# EXPOSE 7000 9042 are already declared by the base; add 9500 for metrics
# scraping parity with the Dockerfile.
env = {"JVM_EXTRA_OPTS": JVM_ADD_OPENS},
exposed_ports = ["9500/tcp"],
tags = ["cassandra"],
tars = [
":yq_layer",
":env_layer",
],
visibility = ["//visibility:public"],
)

# Non-manual handle for the multi-arch image. create_oci_image tags every
# target it emits `manual` (so `bazel run //...` never fires a push/load), but
# that also excludes :image_index from `bazel build //...`. The CI matrix
# (.github/workflows/bazel.yml) builds `//...`, so without a non-manual target
# depending on the index, GHA would never build the image itself. This alias
# pulls the multi-arch index into the wildcard build. Mirrors the
# function-autoscaler `alias` handle for its binary.
alias(
name = "cassandra",
actual = ":image_index",
visibility = ["//visibility:public"],
)

# yq exec-bit guard: fail the build if /usr/local/bin/yq is missing or not
# executable in the assembled layer (rules_pkg pkg_files default-mode 0644
# trap). Mirrors the stargate image_entrypoint_mode_test.
sh_test(
name = "yq_exec_bit_test",
srcs = ["//tools/ci:image_entrypoint_mode_test.sh"],
args = [
"$(location :yq_layer)",
"/usr/local/bin/yq",
],
data = [":yq_layer"],
)

# Version contract: the pinned oci.pull digest in MODULE.bazel is authoritative
# for the built image, but the transitional Dockerfile still carries a
# `FROM cassandra:<tag>`. Fail the build if that tag and the
# `# cassandra-version:` marker recorded next to the digest ever drift, so a
# bump cannot silently ship two different Cassandra versions.
sh_test(
name = "cassandra_version_consistency_test",
size = "small",
srcs = ["//tools/ci:cassandra_version_consistency_test.sh"],
args = [
"$(location Dockerfile)",
"$(location MODULE.bazel)",
],
data = [
"Dockerfile",
"MODULE.bazel",
],
)
106 changes: 106 additions & 0 deletions infra/cassandra/MODULE.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Bzlmod module definition for the NVCF Cassandra runtime image.

Image-assembly only: no language toolchain. This is the Bazel rules_oci
port of infra/cassandra/Dockerfile. It layers, on top of the official
Apache Cassandra base:

- a pinned, checksum-verified `yq` binary at /usr/local/bin/yq (used by
the chart's config init container to deep-merge cassandra.yaml), and
- scripts/cassandra-env.sh at /etc/cassandra/cassandra-env.sh (rack from
pod-hostname suffix for GossipingPropertyFileSnitch).

The public //:image_index target is OSS-safe: no metrics exporter jar and
no tenant registry URLs. The with-exporter variant and the NGC push
destinations live under nvidia-internal/ (excluded from the OSS mirror).

The umbrella nvcf/nvcf lists infra/cassandra in .bazelignore, so this
nested module is built on its own (cd infra/cassandra && bazel build ...),
mirroring the function-autoscaler / stargate pattern.
"""

module(
name = "nvcf_cassandra_image",
version = "0.0.1",
)

bazel_dep(name = "platforms", version = "1.0.0")
bazel_dep(name = "rules_oci", version = "2.2.7")
bazel_dep(name = "rules_pkg", version = "1.2.0")
bazel_dep(name = "aspect_bazel_lib", version = "2.19.3")
bazel_dep(name = "rules_python", version = "1.7.0")
bazel_dep(name = "rules_shell", version = "0.8.0")

# NVCF OCI image-push macro. Data-free module: destination URLs are inlined
# at the nvidia-internal/ call-site, not here, so this override resolves on
# both the private GitLab build and the public NVIDIA/nvcf GitHub mirror.
bazel_dep(name = "nvcf_nvcr_destinations", version = "0.0.0")
local_path_override(
module_name = "nvcf_nvcr_destinations",
path = "../../rules/oci-destinations",
)

# rules_pkg pulls a hermetic Python interpreter for its tar builder. That
# interpreter refuses to run as root unless told otherwise, which the CI
# container hits. ignore_root_user_error keeps `bazel build` green there.
python = use_extension("@rules_python//python/extensions:python.bzl", "python")
python.toolchain(
ignore_root_user_error = True,
python_version = "3.11",
)

# ============================================================================
# OCI base image: official Apache Cassandra (Docker Hub), pinned by the
# multi-arch manifest-list digest below. This digest is authoritative for the
# built image and is the one thing to bump for a Cassandra version change:
# re-resolve the new tag's manifest-list digest. The transitional Dockerfile
# still carries a `FROM cassandra:<tag>` for manual/dev builds; the version
# marker below records the tag this digest resolves, and
# cassandra_version_consistency_test fails CI if the Dockerfile tag and this
# marker drift. Bump all three together; see AGENTS.md. Only linux/amd64 +
# linux/arm64 are selected; the list also carries armv7/ppc64le/s390x, which we
# do not build.
# cassandra-version: 5.0.8
# ============================================================================
oci = use_extension("@rules_oci//oci:extensions.bzl", "oci")
oci.pull(
name = "cassandra_base",
digest = "sha256:e52bb93c21f69cc5c2f5eb9e7d9736b10a047ad38bc7776480c7dbbf7d4e0ba7",
image = "index.docker.io/library/cassandra",
platforms = [
"linux/amd64",
"linux/arm64/v8",
],
)
use_repo(
oci,
"cassandra_base",
"cassandra_base_linux_amd64",
"cassandra_base_linux_arm64_v8",
)

# ============================================================================
# External artifacts fetched by digest: the pinned yq binaries (public,
# OSS-safe). The internal exporter-agent jar is not declared here; the
# with-exporter image is built in nvcf-internal (see //rules:repos.bzl).
# ============================================================================
artifacts = use_extension("//rules:repos.bzl", "external_artifacts")
use_repo(
artifacts,
"yq_linux_amd64",
"yq_linux_arm64",
)
Loading
Loading