Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move install tests shell script into Rust #548

Merged
merged 1 commit into from
May 20, 2024
Merged
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
98 changes: 12 additions & 86 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,26 +68,6 @@ jobs:
with:
name: bootc.tar.zst
path: target/bootc.tar.zst
build-c9s:
if: ${{ !contains(github.event.pull_request.labels.*.name, 'control/skip-ci') }}
runs-on: ubuntu-latest
container: quay.io/centos/centos:stream9
steps:
- run: dnf -y install git-core
- uses: actions/checkout@v4
- name: Install deps
run: ./ci/installdeps.sh
- name: Cache Dependencies
uses: Swatinem/rust-cache@v2
with:
key: "build-c9s"
- name: Build
run: make test-bin-archive
- name: Upload binary
uses: actions/upload-artifact@v4
with:
name: bootc-c9s.tar.zst
path: target/bootc.tar.zst
cargo-deny:
runs-on: ubuntu-latest
steps:
Expand Down Expand Up @@ -127,78 +107,24 @@ jobs:
run: sudo tar -C / -xvf bootc.tar.zst
- name: Integration tests
run: bootc internal-tests run-container-integration
privtest-alongside:
install-tests:
if: ${{ !contains(github.event.pull_request.labels.*.name, 'control/skip-ci') }}
name: "Test install-alongside"
needs: [build-c9s]
runs-on: ubuntu-latest
name: "Test install"
# For a not-ancient podman
runs-on: ubuntu-24.04
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Ensure host skopeo is disabled
run: sudo rm -f /bin/skopeo /usr/bin/skopeo
- name: Download
uses: actions/download-artifact@v4
with:
name: bootc-c9s.tar.zst
- name: Install
run: tar -xvf bootc.tar.zst
- name: Integration tests
run: |
set -xeuo pipefail
image=quay.io/centos-bootc/centos-bootc-dev:stream9
echo 'ssh-ed25519 ABC0123 testcase@example.com' > test_authorized_keys
sudo podman run --rm --privileged -v ./test_authorized_keys:/test_authorized_keys --env RUST_LOG=debug -v /:/target -v /var/lib/containers:/var/lib/containers -v ./usr/bin/bootc:/usr/bin/bootc --pid=host --security-opt label=disable \
${image} bootc install to-filesystem --acknowledge-destructive \
--karg=foo=bar --disable-selinux --replace=alongside --root-ssh-authorized-keys=/test_authorized_keys /target
ls -al /boot/loader/
sudo grep foo=bar /boot/loader/entries/*.conf
grep authorized_keys /ostree/deploy/default/deploy/*/etc/tmpfiles.d/bootc-root-ssh.conf
# TODO fix https://github.com/containers/bootc/pull/137
sudo chattr -i /ostree/deploy/default/deploy/*
sudo rm /ostree/deploy/default -rf
sudo podman run --rm --privileged --env RUST_LOG=debug -v /:/target -v /var/lib/containers:/var/lib/containers -v ./usr/bin/bootc:/usr/bin/bootc --pid=host --security-opt label=disable \
${image} bootc install to-existing-root --acknowledge-destructive
sudo podman run --rm --privileged -v /:/target -v ./usr/bin/bootc:/usr/bin/bootc --pid=host --security-opt label=disable ${image} bootc internal-tests verify-selinux /target/ostree --warn
install-to-existing-root:
if: ${{ !contains(github.event.pull_request.labels.*.name, 'control/skip-ci') }}
name: "Test install-to-existing-root"
needs: [build-c9s]
runs-on: ubuntu-latest
steps:
- name: Download
uses: actions/download-artifact@v4
with:
name: bootc-c9s.tar.zst
- name: Install
run: tar -xvf bootc.tar.zst
- name: Integration tests
run: |
set -xeuo pipefail
# We should be able to install to-existing-root with no install config,
# so we bind mount an empty directory over /usr/lib/bootc/install.
empty=$(mktemp -d)
image=quay.io/centos-bootc/centos-bootc-dev:stream9
sudo podman run --rm --privileged --env RUST_LOG=debug -v /:/target -v /var/lib/containers:/var/lib/containers -v ./usr/bin/bootc:/usr/bin/bootc -v ${empty}:/usr/lib/bootc/install --pid=host --security-opt label=disable \
${image} bootc install to-existing-root
install-to-loopback:
if: ${{ !contains(github.event.pull_request.labels.*.name, 'control/skip-ci') }}
name: "Test install to-disk --via-loopback"
needs: [build-c9s]
runs-on: ubuntu-latest
steps:
- name: Download
uses: actions/download-artifact@v4
with:
name: bootc-c9s.tar.zst
- name: Install
run: tar -xvf bootc.tar.zst
- name: Integration tests
run: |
set -xeuo pipefail
image=quay.io/centos-bootc/centos-bootc-dev:stream9
tmpdisk=$(mktemp -p /var/tmp)
truncate -s 20G ${tmpdisk}
sudo podman run --rm --privileged --env RUST_LOG=debug -v /dev:/dev -v /:/target -v /var/lib/containers:/var/lib/containers -v ./usr/bin/bootc:/usr/bin/bootc --pid=host --security-opt label=disable \
-v ${tmpdisk}:/disk ${image} bootc install to-disk --via-loopback /disk
set -xeu
sudo podman build -t localhost/bootc -f hack/Containerfile .
# Nondestructive but privileged tests
cargo run -p tests-integration host-privileged localhost/bootc
# Finally the install-alongside suite
cargo run -p tests-integration install-alongside localhost/bootc
docs:
if: ${{ contains(github.event.pull_request.labels.*.name, 'documentation') }}
runs-on: ubuntu-latest
Expand Down
84 changes: 84 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[workspace]
members = ["cli", "lib", "xtask"]
members = ["cli", "lib", "xtask", "tests-integration"]
resolver = "2"

[profile.dev]
Expand Down
2 changes: 1 addition & 1 deletion hack/Containerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ WORKDIR /build
RUN mkdir -p /build/target/dev-rootfs # This can hold arbitrary extra content
# See https://www.reddit.com/r/rust/comments/126xeyx/exploring_the_problem_of_faster_cargo_docker/
# We aren't using the full recommendations there, just the simple bits.
RUN --mount=type=cache,target=/build/target --mount=type=cache,target=/var/roothome make bin-archive && mkdir -p /out && cp target/bootc.tar.zst /out
RUN --mount=type=cache,target=/build/target --mount=type=cache,target=/var/roothome make test-bin-archive && mkdir -p /out && cp target/bootc.tar.zst /out

FROM quay.io/centos-bootc/centos-bootc:stream9
COPY --from=build /out/bootc.tar.zst /tmp
Expand Down
8 changes: 4 additions & 4 deletions lib/src/docgen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ pub fn generate_manpages(directory: &Utf8Path) -> Result<()> {
fn generate_one(directory: &Utf8Path, cmd: Command) -> Result<()> {
let version = env!("CARGO_PKG_VERSION");
let name = cmd.get_name();
let bin_name = cmd.get_bin_name()
.unwrap_or_else(|| name);
let bin_name = cmd.get_bin_name().unwrap_or_else(|| name);
let path = directory.join(format!("{name}.8"));
println!("Generating {path}...");

Expand All @@ -37,12 +36,13 @@ fn generate_one(directory: &Utf8Path, cmd: Command) -> Result<()> {

for subcmd in cmd.get_subcommands().filter(|c| !c.is_hide_set()) {
let subname = format!("{}-{}", name, subcmd.get_name());
let bin_name = format!("{} {}", bin_name, subcmd.get_name());
let bin_name = format!("{} {}", bin_name, subcmd.get_name());
// SAFETY: Latest clap 4 requires names are &'static - this is
// not long-running production code, so we just leak the names here.
let subname = &*std::boxed::Box::leak(subname.into_boxed_str());
let bin_name = &*std::boxed::Box::leak(bin_name.into_boxed_str());
let subcmd = subcmd.clone()
let subcmd = subcmd
.clone()
.name(subname)
.alias(subname)
.bin_name(bin_name)
Expand Down
21 changes: 21 additions & 0 deletions tests-integration/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Our integration tests
[package]
name = "tests-integration"
version = "0.1.0"
license = "MIT OR Apache-2.0"
edition = "2021"
publish = false

[[bin]]
name = "tests-integration"
path = "src/tests-integration.rs"

[dependencies]
anyhow = "1.0.82"
camino = "1.1.6"
cap-std-ext = "4"
clap = { version= "4.5.4", features = ["derive","cargo"] }
fn-error-context = "0.2.1"
libtest-mimic = "0.7.3"
tempfile = "3.10.1"
xshell = { version = "0.2.6" }
24 changes: 24 additions & 0 deletions tests-integration/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Integration tests crate

This crate holds integration tests (as distinct from the regular
Rust unit tests run as part of `cargo test`).

## Building and running

`cargo run -p tests-integration`
will work. Note that at the current time all test suites target
an externally built bootc-compatible container image. See
how things are set up in e.g. Github Actions, where we first
run a `podman build` with the bootc git sources.

## Available suites

### `host-privileged`

This suite will run the target container image in a way that expects
full privileges, but is *not* destructive.

### `install-alongside`

This suite is *DESTRUCTIVE*, executing the bootc `install to-existing-root`
style flow using the host root. Run it in a transient virtual machine.
27 changes: 27 additions & 0 deletions tests-integration/src/hostpriv.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use anyhow::Result;
use fn_error_context::context;
use libtest_mimic::Trial;
use xshell::cmd;

/// Tests that require real root (e.g. CAP_SYS_ADMIN) to do things like
/// create loopback devices, but are *not* destructive. At the current time
/// these tests are defined to reference a bootc container image.
#[context("Hostpriv tests")]
pub(crate) fn run_hostpriv(image: &str, testargs: libtest_mimic::Arguments) -> Result<()> {
// Just leak the image name so we get a static reference as required by the test framework
let image: &'static str = String::from(image).leak();
let base_args = super::install::BASE_ARGS;

let tests = [Trial::test("loopback install", move || {
let sh = &xshell::Shell::new()?;
let size = 10 * 1000 * 1000 * 1000;
let mut tmpdisk = tempfile::NamedTempFile::new_in("/var/tmp")?;
tmpdisk.as_file_mut().set_len(size)?;
let tmpdisk = tmpdisk.into_temp_path();
let tmpdisk = tmpdisk.to_str().unwrap();
cmd!(sh, "sudo {base_args...} -v {tmpdisk}:/disk {image} bootc install to-disk --via-loopback --skip-fetch-check /disk").run()?;
Ok(())
})];

libtest_mimic::run(&testargs, tests.into()).exit()
}
Loading
Loading