Skip to content
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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ jobs:
run: sudo apt update && sudo apt install just
- uses: actions/checkout@v4
- name: Build and run container integration tests
run: sudo just run-container-integration
run: sudo just run-container-integration run-container-external-tests
cargo-deny:
runs-on: ubuntu-latest
steps:
Expand Down
4 changes: 4 additions & 0 deletions Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,9 @@ build-integration-test-image *ARGS: build
run-container-integration: build-integration-test-image
podman run --rm localhost/bootc-integration bootc-integration-tests container

# These tests may spawn their own container images.
run-container-external-tests:
./tests/container/run localhost/bootc

unittest *ARGS:
podman build --jobs=4 --target units -t localhost/bootc-units --build-arg=unitargs={{ARGS}} .
4 changes: 4 additions & 0 deletions crates/lib/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,9 @@ pub(crate) enum InternalsOpts {
// The stateroot
stateroot: String,
},
/// Initiate a reboot the same way we would after --apply; intended
/// primarily for testing.
Reboot,
#[cfg(feature = "rhsm")]
/// Publish subscription-manager facts to /etc/rhsm/facts/bootc.facts
PublishRhsmFacts,
Expand Down Expand Up @@ -1230,6 +1233,7 @@ async fn run_from_opt(opt: Opt) -> Result<()> {
Ok(())
}
},
InternalsOpts::Reboot => crate::reboot::reboot(),
InternalsOpts::Fsck => {
let sysroot = &get_storage().await?;
crate::fsck::fsck(&sysroot, std::io::stdout().lock()).await?;
Expand Down
11 changes: 11 additions & 0 deletions tests/container/reboot/bootc-finish-test-reboot.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[Unit]
ConditionPathExists=!/etc/initrd-release
After=local-fs.target
RequiresMountsFor=/run/bootc-test-reboot
Before=bootc-test-reboot.service
PartOf=bootc-test-reboot.service

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStop=touch /run/bootc-test-reboot/success
12 changes: 12 additions & 0 deletions tests/container/reboot/bootc-test-reboot.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[Unit]
ConditionPathExists=!/etc/initrd-release
Requires=bootc-finish-test-reboot.service
After=bootc-finish-test-reboot.service

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=bootc internals reboot

[Install]
WantedBy=multi-user.target
22 changes: 22 additions & 0 deletions tests/container/reboot/run
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/bin/bash
# Verify that invoking `bootc internals reboot` actually invokes a reboot, when
# running inside systemd.
# xref:
# - https://github.com/bootc-dev/bootc/issues/1416
# - https://github.com/bootc-dev/bootc/issues/1419
set -euo pipefail
image=$1
tmpd=$(mktemp -d)
log() {
echo "$@"
"$@"
}
log timeout 120 podman run --rm --systemd=always --privileged -v /sys:/sys:ro --label bootc.test=reboot --net=none -v $(pwd):/src:ro -v $tmpd:/run/bootc-test-reboot $image /bin/sh -c 'cp /src/*.service /etc/systemd/system && systemctl enable bootc-test-reboot && exec /sbin/init' || true
ls -al $tmpd
if test '!' -f $tmpd/success; then
echo "reboot failed" 1>&2
rm -rf "$tmpd"
exit 1
fi
rm -rf "$tmpd"
echo "ok reboot"
16 changes: 16 additions & 0 deletions tests/container/run
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/bin/bash
set -euo pipefail
image=$1
shift

cd $(dirname $0)

tests=$(find . -maxdepth 1 -type d)
for case in $tests; do
if test $case = .; then continue; fi
echo "Running: $case"
cd $case
./run $image
cd -
Comment on lines +12 to +14
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using a subshell (...) to run commands in a different directory is often cleaner and safer than cd ...; cd -.

find . -maxdepth 1 -type d -print0 | while IFS= read -r -d '' case; do
  if [ "$case" = "." ]; then continue; fi
  echo "Running: $case"
  (
    cd -- "$case" && ./run "$image"
  )
  echo "ok $case"
done

echo "ok $case"
done
Comment on lines +9 to +16
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The for case in $tests loop is subject to word splitting, which will cause issues with directory names that contain spaces or other special characters. Using a while read loop with find -print0 is the standard, robust way to iterate over find's output.

find . -maxdepth 1 -type d -print0 | while IFS= read -r -d '' case; do
  if [ "$case" = "." ]; then continue; fi
  echo "Running: $case"
  cd $case
  ./run $image
  cd -
  echo "ok $case"
done

Comment on lines +6 to +16
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Path variables like $(dirname "$0") and $case should be quoted.

cd "$(dirname "$0")"

find . -maxdepth 1 -type d -print0 | while IFS= read -r -d '' case; do
  if [ "$case" = "." ]; then continue; fi
  echo "Running: $case"
  cd "$case"
  ./run $image
  cd -
  echo "ok $case"
done