| 
 | 1 | +#!/usr/bin/env bats  | 
 | 2 | + | 
 | 3 | +load helpers  | 
 | 4 | + | 
 | 5 | +function setup() {  | 
 | 6 | +	INITRAMFS_ROOT="$(mktemp -d "$BATS_RUN_TMPDIR/runc-initramfs.XXXXXX")"  | 
 | 7 | +}  | 
 | 8 | + | 
 | 9 | +function teardown() {  | 
 | 10 | +	[ -v INITRAMFS_ROOT ] && rm -rf "$INITRAMFS_ROOT"  | 
 | 11 | +}  | 
 | 12 | + | 
 | 13 | +function qemu_native() {  | 
 | 14 | +	# Different distributions put qemu-kvm in different locations and with  | 
 | 15 | +	# different names. Debian and Ubuntu have a "kvm" binary, while AlmaLinux  | 
 | 16 | +	# has /usr/libexec/qemu-kvm.  | 
 | 17 | +	qemu_candidates=("kvm" "qemu-kvm" "/usr/libexec/qemu-kvm")  | 
 | 18 | + | 
 | 19 | +	qemu_binary=  | 
 | 20 | +	for candidate in "${qemu_candidates[@]}"; do  | 
 | 21 | +		"$candidate" -help &>/dev/null || continue  | 
 | 22 | +		qemu_binary="$candidate"  | 
 | 23 | +		break  | 
 | 24 | +	done  | 
 | 25 | +	# TODO: Maybe we should also try to call qemu-system-FOO for the current  | 
 | 26 | +	# architecture if qemu-kvm is missing?  | 
 | 27 | +	[ -n "$qemu_binary" ] || skip "could not find qemu-kvm binary"  | 
 | 28 | + | 
 | 29 | +	sane_run "$qemu_binary" "$@"  | 
 | 30 | +}  | 
 | 31 | + | 
 | 32 | +@test "runc run [initramfs + pivot_root]" {  | 
 | 33 | +	requires root  | 
 | 34 | + | 
 | 35 | +	# Configure our minimal initrd.  | 
 | 36 | +	mkdir -p "$INITRAMFS_ROOT/initrd"  | 
 | 37 | +	pushd "$INITRAMFS_ROOT/initrd"  | 
 | 38 | + | 
 | 39 | +	# Use busybox as a base for our initrd.  | 
 | 40 | +	tar --exclude './dev/*' -xf "$BUSYBOX_IMAGE"  | 
 | 41 | +	# Make sure that "sh" and "poweroff" are installed, otherwise qemu will  | 
 | 42 | +	# boot loop when init stops.  | 
 | 43 | +	[ -x ./bin/sh ] || skip "busybox image is missing /bin/sh"  | 
 | 44 | +	[ -x ./bin/poweroff ] || skip "busybox image is missing /bin/poweroff"  | 
 | 45 | + | 
 | 46 | +	# Copy the runc binary into the container. In theory we would prefer to  | 
 | 47 | +	# copy a static binary, but some distros (like openSUSE) don't ship  | 
 | 48 | +	# libseccomp-static so requiring a static build for any integration test  | 
 | 49 | +	# run wouldn't work. Instead, we copy all of the library dependencies into  | 
 | 50 | +	# the rootfs (note that we also have to copy ld-linux-*.so because runc was  | 
 | 51 | +	# probably built with a newer glibc than the one in our busybox image.  | 
 | 52 | +	cp "$RUNC" ./bin/runc  | 
 | 53 | +	readarray -t runclibs \  | 
 | 54 | +		<<<"$(ldd "$RUNC" | grep -Eo '/[^ ]*lib[^ ]*.so.[^ ]*')"  | 
 | 55 | +	mkdir -p ./lib{,64}  | 
 | 56 | +	cp -vt ./lib/ "${runclibs[@]}"  | 
 | 57 | +	cp -vt ./lib64/ "${runclibs[@]}"  | 
 | 58 | + | 
 | 59 | +	# Create a container bundle using the same busybox image.  | 
 | 60 | +	mkdir -p ./run/bundle  | 
 | 61 | +	pushd ./run/bundle  | 
 | 62 | +	mkdir -p rootfs  | 
 | 63 | +	tar --exclude './dev/*' -C rootfs -xf "$BUSYBOX_IMAGE"  | 
 | 64 | +	runc spec  | 
 | 65 | +	update_config '.process.args = ["/bin/echo", "hello from inside the container"]'  | 
 | 66 | +	popd  | 
 | 67 | + | 
 | 68 | +	# Build a custom /init script.  | 
 | 69 | +	cat >./init <<-EOF  | 
 | 70 | +		#!/bin/sh  | 
 | 71 | +
  | 
 | 72 | +		set -x  | 
 | 73 | +		echo "==START INIT SCRIPT=="  | 
 | 74 | +
  | 
 | 75 | +		mkdir -p /proc /sys  | 
 | 76 | +		mount -t proc proc /proc  | 
 | 77 | +		mkdir -p /sys  | 
 | 78 | +		mount -t sysfs sysfs /sys  | 
 | 79 | +
  | 
 | 80 | +		mkdir -p /sys/fs/cgroup  | 
 | 81 | +		mount -t cgroup2 cgroup2 /sys/fs/cgroup  | 
 | 82 | +
  | 
 | 83 | +		mkdir -p /tmp  | 
 | 84 | +		mount -t tmpfs tmpfs /tmp  | 
 | 85 | +
  | 
 | 86 | +		mkdir -p /dev  | 
 | 87 | +		mount -t devtmpfs devtmpfs /dev  | 
 | 88 | +		mkdir -p /dev/pts  | 
 | 89 | +		mount -t devpts -o newinstance devpts /dev/pts  | 
 | 90 | +		mkdir -p /dev/shm  | 
 | 91 | +		mount --bind /tmp /dev/shm  | 
 | 92 | +
  | 
 | 93 | +		runc run -b /run/bundle ctr  | 
 | 94 | +
  | 
 | 95 | +		echo "==END INIT SCRIPT=="  | 
 | 96 | +		poweroff -f  | 
 | 97 | +	EOF  | 
 | 98 | +	chmod +x ./init  | 
 | 99 | + | 
 | 100 | +	find . | cpio -o -H newc >"$INITRAMFS_ROOT/initrd.cpio"  | 
 | 101 | +	popd  | 
 | 102 | + | 
 | 103 | +	# Now we can just run the image (use qemu-kvm so that we run on the same  | 
 | 104 | +	# architecture as the host system). We can just reuse the host kernel.  | 
 | 105 | +	qemu_native \  | 
 | 106 | +		-initrd "$INITRAMFS_ROOT/initrd.cpio" \  | 
 | 107 | +		-kernel /boot/vmlinuz \  | 
 | 108 | +		-m 512M \  | 
 | 109 | +		-nographic -append console=ttyS0  | 
 | 110 | +	[ "$status" -eq 0 ]  | 
 | 111 | +	[[ "$output" = *"==START INIT SCRIPT=="* ]]  | 
 | 112 | +	[[ "$output" = *"hello from inside the container"* ]]  | 
 | 113 | +	[[ "$output" = *"==END INIT SCRIPT=="* ]]  | 
 | 114 | +}  | 
0 commit comments