mirror of
https://github.com/opencontainers/runc.git
synced 2026-07-11 06:03:57 +08:00
Merge pull request #3000 from kolyshkin/test-dev-update
libct/int: add device update test
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
package integration
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/opencontainers/runc/libcontainer"
|
||||
"github.com/opencontainers/runc/libcontainer/cgroups/systemd"
|
||||
"github.com/opencontainers/runc/libcontainer/devices"
|
||||
)
|
||||
|
||||
func testUpdateDevices(t *testing.T, systemd bool) {
|
||||
if testing.Short() {
|
||||
return
|
||||
}
|
||||
rootfs, err := newRootfs()
|
||||
ok(t, err)
|
||||
defer remove(rootfs)
|
||||
config := newTemplateConfig(t, &tParam{
|
||||
rootfs: rootfs,
|
||||
systemd: systemd,
|
||||
})
|
||||
container, err := newContainer(t, config)
|
||||
ok(t, err)
|
||||
defer destroyContainer(container)
|
||||
|
||||
// Execute a first process in the container
|
||||
stdinR, stdinW, err := os.Pipe()
|
||||
ok(t, err)
|
||||
process := &libcontainer.Process{
|
||||
Cwd: "/",
|
||||
Args: []string{"cat"},
|
||||
Env: standardEnvironment,
|
||||
Stdin: stdinR,
|
||||
Init: true,
|
||||
}
|
||||
err = container.Run(process)
|
||||
_ = stdinR.Close()
|
||||
defer func() {
|
||||
_ = stdinW.Close()
|
||||
if _, err := process.Wait(); err != nil {
|
||||
t.Log(err)
|
||||
}
|
||||
}()
|
||||
ok(t, err)
|
||||
|
||||
var buf bytes.Buffer
|
||||
devCheck := &libcontainer.Process{
|
||||
Cwd: "/",
|
||||
Args: []string{"/bin/sh", "-c", "echo > /dev/full; cat /dev/null; true"},
|
||||
Env: standardEnvironment,
|
||||
Stderr: &buf,
|
||||
}
|
||||
isAllowed := true
|
||||
expected := map[bool][]string{
|
||||
true: {
|
||||
"write error: No space left on device", // from write to /dev/full
|
||||
// no error from cat /dev/null
|
||||
},
|
||||
false: {
|
||||
"/dev/full: Operation not permitted",
|
||||
`cat: can't open '/dev/null': Operation not permitted`,
|
||||
},
|
||||
}
|
||||
defaultDevices := config.Cgroups.Resources.Devices
|
||||
|
||||
for i := 0; i < 300; i++ {
|
||||
// Check the access
|
||||
buf.Reset()
|
||||
err = container.Run(devCheck)
|
||||
ok(t, err)
|
||||
waitProcess(devCheck, t)
|
||||
|
||||
for _, exp := range expected[isAllowed] {
|
||||
if !strings.Contains(buf.String(), exp) {
|
||||
t.Fatalf("[%d] expected %q, got %q", i, exp, buf.String())
|
||||
}
|
||||
}
|
||||
|
||||
// Now flip the access permission
|
||||
isAllowed = !isAllowed
|
||||
if isAllowed {
|
||||
config.Cgroups.Resources.Devices = defaultDevices
|
||||
} else {
|
||||
config.Cgroups.Resources.Devices = []*devices.Rule{}
|
||||
}
|
||||
if err := container.Set(*config); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateDevices(t *testing.T) {
|
||||
testUpdateDevices(t, false)
|
||||
}
|
||||
|
||||
func TestUpdateDevicesSystemd(t *testing.T) {
|
||||
if !systemd.IsRunningSystemd() {
|
||||
t.Skip("Test requires systemd.")
|
||||
}
|
||||
testUpdateDevices(t, true)
|
||||
}
|
||||
@@ -648,29 +648,3 @@ EOF
|
||||
runc resume test_update
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "runc update replaces devices cgroup program" {
|
||||
[[ "$ROOTLESS" -ne 0 ]] && requires rootless_cgroup
|
||||
|
||||
# Unfortunately we can't update device rules directly with runc ("runc
|
||||
# update" doesn't support it, and adding support would require ironing out
|
||||
# some long-standing design issues with device configuration). So instead
|
||||
# we just run "runc update" many times, relying on the fact that runc will
|
||||
# re-apply devices cgroup rules on each runc update.
|
||||
#
|
||||
# In the past runc would not delete old cgroupv2 eBPF programs, so this
|
||||
# test ensures that once we go past the program limit (64 stacked programs
|
||||
# at time of writing) you can still run "runc" update.
|
||||
|
||||
# Run the container in the background.
|
||||
runc run -d --console-socket "$CONSOLE_SOCKET" test_update
|
||||
[ "$status" -eq 0 ]
|
||||
|
||||
for new_limit in $(seq 300); do
|
||||
runc update --pids-limit "$((2 * new_limit))" test_update
|
||||
[ "$status" -eq 0 ]
|
||||
done
|
||||
|
||||
# The container should still be running.
|
||||
testcontainer test_update running
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user