mirror of
https://github.com/containerd/containerd.git
synced 2026-11-06 05:17:02 +00:00
ci: add integration-runsc CI job and script/runsc/ test helpers
Co-authored-by: Wei Fu <fuweid89@gmail.com> Signed-off-by: Mike Brown <brownwm@us.ibm.com>
This commit is contained in:
1 parent
c787e39387
commit
fc774e4b3c
42 files changed
+1289
-50
No files matched your search
+108
-1
@@ -693,6 +693,113 @@ jobs:
|
||||
LIMA_WORKDIR: /
|
||||
run: lima sudo dmesg -T -f kern
|
||||
|
||||
|
||||
integration-runsc:
|
||||
name: runsc (gVisor) integration
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 60
|
||||
needs: [project, linters, protos, man]
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
cgroup_driver: [systemd, cgroupfs]
|
||||
|
||||
env:
|
||||
CGROUP_DRIVER: ${{ matrix.cgroup_driver }}
|
||||
TEST_RUNTIME: io.containerd.runsc.v1
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: ./.github/actions/install-go
|
||||
|
||||
- name: Install containerd dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y gperf dmsetup strace xfsprogs
|
||||
script/setup/install-seccomp
|
||||
script/setup/install-runc
|
||||
script/setup/install-cni $(grep containernetworking/plugins go.mod | awk '{print $2}')
|
||||
script/setup/install-critools
|
||||
script/setup/install-failpoint-binaries
|
||||
|
||||
- name: Install runsc (gVisor)
|
||||
run: script/runsc/install-runsc
|
||||
|
||||
- name: Build containerd
|
||||
env:
|
||||
CGO_ENABLED: 1
|
||||
run: |
|
||||
make binaries GO_BUILD_FLAGS="-mod=vendor"
|
||||
sudo -E PATH=$PATH make install
|
||||
|
||||
- name: CRI integration (runsc)
|
||||
run: |
|
||||
# Generate the runsc containerd config and pass it to cri-integration
|
||||
# so utils.sh skips its own config generation.
|
||||
cfg=$(mktemp /tmp/containerd-config-runsc-XXXXXX.toml)
|
||||
trap 'rm -f "$cfg"' EXIT
|
||||
script/runsc/write-runsc-shim-config.sh "$CGROUP_DRIVER" systrap
|
||||
script/runsc/write-containerd-runsc-config.sh "$cfg" "$CGROUP_DRIVER"
|
||||
# The external config and runsc shim config already contain the cgroup settings.
|
||||
# Keep CGROUP_DRIVER set but empty so utils.sh does not append runc.options again.
|
||||
CGROUP_DRIVER= CONTAINERD_CONFIG_FILE="$cfg" RUNTIME=runsc RUNTIME_TYPE=io.containerd.runsc.v1 make cri-integration
|
||||
|
||||
- name: Runsc memory baseline
|
||||
run: |
|
||||
set -eux
|
||||
free -h
|
||||
cat /proc/meminfo | grep -E 'MemAvailable|SwapFree|SwapTotal'
|
||||
systemctl show containerd --property=MemoryMax --property=MemoryHigh || true
|
||||
sudo systemd-cgtop -b -n 1 || true
|
||||
|
||||
- name: critest (runsc)
|
||||
env:
|
||||
GOMAXPROCS: "2"
|
||||
GINKGO_NODES: "2"
|
||||
GOMEMLIMIT: "4GiB"
|
||||
run: |
|
||||
mkdir -p "${{github.workspace}}/report"
|
||||
cfg=$(mktemp /tmp/containerd-config-runsc-XXXXXX.toml)
|
||||
trap 'rm -f "$cfg"' EXIT
|
||||
script/runsc/write-containerd-runsc-config.sh "$cfg" "$CGROUP_DRIVER"
|
||||
sudo -E \
|
||||
CGROUP_DRIVER="$CGROUP_DRIVER" \
|
||||
CONTAINERD_CONFIG_FILE="$cfg" \
|
||||
GOMAXPROCS="$GOMAXPROCS" \
|
||||
GOMEMLIMIT="$GOMEMLIMIT" \
|
||||
GINKGO_NODES="$GINKGO_NODES" \
|
||||
PATH="$PATH" \
|
||||
script/runsc/critest-runsc.sh "${{github.workspace}}/report"
|
||||
|
||||
- name: Host Status
|
||||
if: always()
|
||||
run: |
|
||||
free -h
|
||||
df -h
|
||||
ps aux --sort=-%mem | head -n 30
|
||||
sudo systemctl status containerd --no-pager || true
|
||||
sudo journalctl -k --no-pager -n 200 || true
|
||||
sudo dmesg -T | grep -iE 'oom|out of memory|killed process' || true
|
||||
|
||||
- name: Kernel Message
|
||||
if: failure()
|
||||
run: |
|
||||
sudo dmesg -T | tail -n 200 || true
|
||||
|
||||
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
if: always()
|
||||
with:
|
||||
name: TestResults-runsc-${{ matrix.cgroup_driver }}
|
||||
path: |
|
||||
*-junit.xml
|
||||
*-gotest.json
|
||||
${{github.workspace}}/report/*.xml
|
||||
${{github.workspace}}/report/*.log
|
||||
|
||||
|
||||
tests-cri-in-userns:
|
||||
name: "CRI-in-UserNS"
|
||||
|
||||
@@ -796,7 +903,7 @@ jobs:
|
||||
name: Report required job statuses
|
||||
runs-on: ubuntu-24.04
|
||||
# List job dependencies which are required to pass status checks in order to be merged via merge queue.
|
||||
needs: [linters, project, protos, binaries, integration-linux, integration-windows, tests-cri-in-userns, tests-mac-os, node-e2e]
|
||||
needs: [linters, project, protos, binaries, integration-linux, integration-windows, integration-runsc, tests-cri-in-userns, tests-mac-os, node-e2e]
|
||||
if: ${{ always() }}
|
||||
steps:
|
||||
- run: exit 1
|
||||
|
||||
@@ -383,7 +383,12 @@ func readContainer(container *containers.Container, bkt *bolt.Bucket) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
container.Runtime.Options = o
|
||||
// Avoid assigning a typed-nil (*anypb.Any)(nil) to the typeurl.Any
|
||||
// interface, which would produce a non-nil interface value that
|
||||
// fails type-URL lookup.
|
||||
if o != nil {
|
||||
container.Runtime.Options = o
|
||||
}
|
||||
case string(bucketKeySpec):
|
||||
var spec types.Any
|
||||
if err := proto.Unmarshal(v, &spec); err != nil {
|
||||
|
||||
@@ -721,3 +721,41 @@ func testEnv(t *testing.T) (context.Context, *bolt.DB) {
|
||||
|
||||
return ctx, db
|
||||
}
|
||||
|
||||
// TestContainerNilRuntimeOptionsRoundTrip verifies that a container stored
|
||||
// without Runtime.Options round-trips back with a genuinely nil interface
|
||||
// value, not a typed-nil *types.Any wrapped in a typeurl.Any interface.
|
||||
//
|
||||
// checkContainersEqual uses compareNil, which treats a typed-nil pointer
|
||||
// wrapped in an interface as equal to a true nil interface and therefore would
|
||||
// not catch this regression. A non-nil interface with a nil underlying pointer
|
||||
// causes type-URL lookup failures at runtime.
|
||||
func TestContainerNilRuntimeOptionsRoundTrip(t *testing.T) {
|
||||
ctx, db := testEnv(t)
|
||||
store := NewContainerStore(NewDB(db, nil, nil))
|
||||
|
||||
spec := &specs.Spec{}
|
||||
encoded, err := typeurl.MarshalAnyToProto(spec)
|
||||
require.NoError(t, err)
|
||||
|
||||
in := containers.Container{
|
||||
ID: "nil-runtime-opts",
|
||||
Spec: encoded,
|
||||
Runtime: containers.RuntimeInfo{
|
||||
Name: "testruntime",
|
||||
// Options intentionally left nil.
|
||||
},
|
||||
}
|
||||
|
||||
_, err = store.Create(ctx, in)
|
||||
require.NoError(t, err)
|
||||
|
||||
out, err := store.Get(ctx, "nil-runtime-opts")
|
||||
require.NoError(t, err)
|
||||
|
||||
// Use direct interface comparison — not compareNil — to distinguish a
|
||||
// true nil interface from a typed-nil pointer wrapped in an interface.
|
||||
if out.Runtime.Options != nil {
|
||||
t.Errorf("Runtime.Options: want nil interface, got %T(%v)", out.Runtime.Options, out.Runtime.Options)
|
||||
}
|
||||
}
|
||||
@@ -371,10 +371,15 @@ func (s *sandboxStore) read(parent *bbolt.Bucket, id []byte) (api.Sandbox, error
|
||||
return api.Sandbox{}, err
|
||||
}
|
||||
|
||||
inst.Spec, err = boltutil.ReadAny(bucket, bucketKeySpec)
|
||||
spec, err := boltutil.ReadAny(bucket, bucketKeySpec)
|
||||
if err != nil {
|
||||
return api.Sandbox{}, err
|
||||
}
|
||||
// Avoid assigning a typed-nil (*anypb.Any)(nil) to the typeurl.Any interface,
|
||||
// which would produce a non-nil interface value that fails type-URL lookup.
|
||||
if spec != nil {
|
||||
inst.Spec = spec
|
||||
}
|
||||
|
||||
runtimeBucket := bucket.Bucket(bucketKeyRuntime)
|
||||
if runtimeBucket == nil {
|
||||
@@ -382,10 +387,13 @@ func (s *sandboxStore) read(parent *bbolt.Bucket, id []byte) (api.Sandbox, error
|
||||
}
|
||||
|
||||
inst.Runtime.Name = string(runtimeBucket.Get(bucketKeyName))
|
||||
inst.Runtime.Options, err = boltutil.ReadAny(runtimeBucket, bucketKeyOptions)
|
||||
runtimeOpts, err := boltutil.ReadAny(runtimeBucket, bucketKeyOptions)
|
||||
if err != nil {
|
||||
return api.Sandbox{}, err
|
||||
}
|
||||
if runtimeOpts != nil {
|
||||
inst.Runtime.Options = runtimeOpts
|
||||
}
|
||||
|
||||
inst.Extensions, err = boltutil.ReadExtensions(bucket)
|
||||
if err != nil {
|
||||
|
||||
@@ -264,3 +264,40 @@ func assertEqualInstances(t *testing.T, x, y api.Sandbox) {
|
||||
t.Fatalf("x and y are different: %s", diff)
|
||||
}
|
||||
}
|
||||
|
||||
// TestSandboxNilInterfaceRoundTrip verifies that a sandbox stored without a
|
||||
// Spec or Runtime.Options round-trips back with genuinely nil interface values.
|
||||
//
|
||||
// compareNil (used by assertEqualInstances) treats a typed-nil pointer wrapped
|
||||
// in an interface as equal to a true nil interface, so it would not catch a
|
||||
// regression where ReadAny returns (*types.Any)(nil) and that typed-nil is
|
||||
// stored directly in the typeurl.Any field — producing a non-nil interface
|
||||
// that fails type-URL lookup at runtime.
|
||||
func TestSandboxNilInterfaceRoundTrip(t *testing.T) {
|
||||
ctx, db := testDB(t)
|
||||
store := NewSandboxStore(db)
|
||||
|
||||
in := api.Sandbox{
|
||||
ID: "nil-fields",
|
||||
Runtime: api.RuntimeOpts{Name: "test"},
|
||||
// Spec and Runtime.Options are intentionally left nil.
|
||||
}
|
||||
|
||||
if _, err := store.Create(ctx, in); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
out, err := store.Get(ctx, "nil-fields")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Use direct interface comparison — not compareNil — to distinguish a
|
||||
// true nil interface from a typed-nil pointer wrapped in an interface.
|
||||
if out.Spec != nil {
|
||||
t.Errorf("Spec: want nil interface, got %T(%v)", out.Spec, out.Spec)
|
||||
}
|
||||
if out.Runtime.Options != nil {
|
||||
t.Errorf("Runtime.Options: want nil interface, got %T(%v)", out.Runtime.Options, out.Runtime.Options)
|
||||
}
|
||||
}
|
||||
+16
-6
@@ -57,12 +57,22 @@ kubeadm users should also see [the kubeadm documentation](https://kubernetes.io/
|
||||
> runtime and the `KubeletConfiguration` configuration step above is not
|
||||
> needed.
|
||||
>
|
||||
> When determining the cgroup driver, containerd uses the `SystemdCgroup`
|
||||
> setting from runc-based runtime classes, starting from the default runtime
|
||||
> class. If no runc-based runtime classes have been configured containerd
|
||||
> relies on auto-detection based on determining if systemd is running.
|
||||
> Note that all runc-based runtime classes should be configured to have the
|
||||
> same `SystemdCgroup` setting in order to avoid unexpected behavior.
|
||||
> When determining the cgroup driver, containerd inspects the runtime classes
|
||||
> in order, starting from the default runtime class:
|
||||
>
|
||||
> - For runc-based runtime classes (`io.containerd.runc.v2`), containerd reads
|
||||
> the `SystemdCgroup` field from the runtime's `options` block.
|
||||
> - For generic shims that use `runtimeoptions/v1` (e.g. `io.containerd.runsc.v1`
|
||||
> for gVisor), containerd reads the cgroup driver from the shim's config file
|
||||
> (`ConfigPath`) or inline config body (`ConfigBody`). It first looks for a
|
||||
> top-level `SystemdCgroup` key (boolean), then for
|
||||
> `[runsc_config] systemd-cgroup` which the runsc shim stores as a TOML string
|
||||
> (`"true"` or `"false"`).
|
||||
> - If no runtime class provides cgroup driver information, containerd falls back
|
||||
> to auto-detection based on whether systemd is running.
|
||||
>
|
||||
> Note that all runtime classes should be configured with the same cgroup driver
|
||||
> setting in order to avoid unexpected behavior.
|
||||
>
|
||||
> The automatic cgroup driver configuration for kubelet feature is supported in
|
||||
> containerd v2.0 and later.
|
||||
|
||||
@@ -28,6 +28,14 @@ import (
|
||||
)
|
||||
|
||||
func TestPrivilegedContainerCgroupMountOptions(t *testing.T) {
|
||||
if runtimeHandlerIsRunsc() {
|
||||
// This test verifies that the host /sys/fs/cgroup mount options
|
||||
// (nsdelegate, memory_recursiveprot) are preserved after running a
|
||||
// privileged container — a runc-specific cgroup namespace concern.
|
||||
// gVisor containers never modify the host cgroup mount, so the test
|
||||
// is not applicable under runsc.
|
||||
t.Skip("host cgroup mount option test is not applicable to runsc")
|
||||
}
|
||||
if cgroups.Mode() != cgroups.Unified {
|
||||
t.Skip("Requires cgroup v2")
|
||||
}
|
||||
|
||||
@@ -28,6 +28,9 @@ import (
|
||||
)
|
||||
|
||||
func TestContainerDrainExecIOAfterExit(t *testing.T) {
|
||||
if runtimeHandlerIsRunsc() {
|
||||
t.Skip("runsc does not support draining exec IO for background processes")
|
||||
}
|
||||
// FIXME(fuweid): support it for windows container.
|
||||
if runtime.GOOS == "windows" {
|
||||
t.Skip("it seems that windows platform doesn't support detached process. skip it")
|
||||
|
||||
@@ -33,6 +33,11 @@ func TestContainerIOLeakAfterStartFailed(t *testing.T) {
|
||||
if f := os.Getenv("RUNC_FLAVOR"); f != "" && f != "runc" {
|
||||
t.Skip("test requires runc")
|
||||
}
|
||||
if runtimeHandlerIsRunsc() {
|
||||
// getShimPid connects to the per-sandbox shim ttrpc socket, which is
|
||||
// a runc-shim implementation detail not available under runsc.
|
||||
t.Skip("getShimPid introspection is runc-shim-specific, not applicable to runsc")
|
||||
}
|
||||
t.Log("Create a sandbox")
|
||||
sb, sbConfig := PodSandboxConfigWithCleanup(t, "sandbox", "container-io-leak-after-start-failed")
|
||||
testImage := images.Get(images.BusyBox)
|
||||
|
||||
@@ -31,6 +31,9 @@ import (
|
||||
|
||||
// Test to verify for a container ID
|
||||
func TestContainerStats(t *testing.T) {
|
||||
if runtimeHandlerIsRunsc() {
|
||||
t.Skip("runsc does not expose per-container CPU nanosecond stats")
|
||||
}
|
||||
t.Logf("Create a pod config and run sandbox container")
|
||||
sb, sbConfig := PodSandboxConfigWithCleanup(t, "sandbox1", "stats")
|
||||
|
||||
@@ -73,6 +76,9 @@ func TestContainerStats(t *testing.T) {
|
||||
|
||||
// Test to verify if the consumed stats are correct.
|
||||
func TestContainerConsumedStats(t *testing.T) {
|
||||
if runtimeHandlerIsRunsc() {
|
||||
t.Skip("runsc does not expose per-container memory working-set stats")
|
||||
}
|
||||
t.Logf("Create a pod config and run sandbox container")
|
||||
sb, sbConfig := PodSandboxConfigWithCleanup(t, "sandbox1", "stats")
|
||||
|
||||
@@ -129,7 +135,7 @@ func TestContainerConsumedStats(t *testing.T) {
|
||||
}
|
||||
|
||||
go func() {
|
||||
_, _, err = runtimeService.ExecSync(cn, command, 30*time.Second)
|
||||
_, _, _ = runtimeService.ExecSync(cn, command, 30*time.Second)
|
||||
}()
|
||||
|
||||
require.NoError(t, Eventually(func() (bool, error) {
|
||||
@@ -146,6 +152,9 @@ func TestContainerConsumedStats(t *testing.T) {
|
||||
|
||||
// Test to verify filtering without any filter
|
||||
func TestContainerListStats(t *testing.T) {
|
||||
if runtimeHandlerIsRunsc() {
|
||||
t.Skip("runsc does not expose per-container CPU nanosecond stats")
|
||||
}
|
||||
var (
|
||||
stats []*runtime.ContainerStats
|
||||
err error
|
||||
@@ -201,6 +210,9 @@ func TestContainerListStats(t *testing.T) {
|
||||
// Test to verify filtering given a specific container ID
|
||||
// TODO Convert the filter tests into table driven tests and unit tests
|
||||
func TestContainerListStatsWithIdFilter(t *testing.T) {
|
||||
if runtimeHandlerIsRunsc() {
|
||||
t.Skip("runsc does not expose per-container CPU nanosecond stats")
|
||||
}
|
||||
var (
|
||||
stats []*runtime.ContainerStats
|
||||
err error
|
||||
@@ -261,6 +273,9 @@ func TestContainerListStatsWithIdFilter(t *testing.T) {
|
||||
// Test to verify filtering given a specific Sandbox ID. Stats for
|
||||
// all the containers in a pod should be returned
|
||||
func TestContainerListStatsWithSandboxIdFilter(t *testing.T) {
|
||||
if runtimeHandlerIsRunsc() {
|
||||
t.Skip("runsc does not expose per-container CPU nanosecond stats")
|
||||
}
|
||||
var (
|
||||
stats []*runtime.ContainerStats
|
||||
err error
|
||||
@@ -322,6 +337,9 @@ func TestContainerListStatsWithSandboxIdFilter(t *testing.T) {
|
||||
// Test to verify filtering given a specific container ID and
|
||||
// sandbox ID
|
||||
func TestContainerListStatsWithIdSandboxIdFilter(t *testing.T) {
|
||||
if runtimeHandlerIsRunsc() {
|
||||
t.Skip("runsc does not expose per-container CPU nanosecond stats")
|
||||
}
|
||||
var (
|
||||
stats []*runtime.ContainerStats
|
||||
err error
|
||||
@@ -430,6 +448,9 @@ func testStats(t *testing.T,
|
||||
}
|
||||
|
||||
func TestContainerSysfsStatsWithPrivilegedPod(t *testing.T) {
|
||||
if runtimeHandlerIsRunsc() {
|
||||
t.Skip("Privileged containers are not supported by runsc")
|
||||
}
|
||||
if goruntime.GOOS == "windows" {
|
||||
t.Skip("Doesn't care about filesystem properties on windows")
|
||||
}
|
||||
|
||||
@@ -33,6 +33,9 @@ func TestContainerStopSignals(t *testing.T) {
|
||||
if goruntime.GOOS == "windows" {
|
||||
t.Skip("Skipped on Windows.")
|
||||
}
|
||||
if runtimeHandlerIsRunsc() {
|
||||
t.Skip("runsc does not support host network")
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
@@ -130,6 +133,9 @@ func TestDefaultContainerStopSignal(t *testing.T) {
|
||||
if goruntime.GOOS == "windows" {
|
||||
t.Skip("Skipped on Windows.")
|
||||
}
|
||||
if runtimeHandlerIsRunsc() {
|
||||
t.Skip("runsc does not support host network")
|
||||
}
|
||||
|
||||
t.Logf("Create a pod config")
|
||||
sb, sbConfig := PodSandboxConfigWithCleanup(t, "sandbox", "default-stop-signal", WithHostNetwork)
|
||||
|
||||
@@ -34,6 +34,9 @@ func TestSharedPidMultiProcessContainerStop(t *testing.T) {
|
||||
"podpid": PodSandboxConfig("sandbox", "pod-pid-container-stop", WithPodPid),
|
||||
} {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
if name == "hostpid" && runtimeHandlerIsRunsc() {
|
||||
t.Skip("runsc does not support host PID namespace")
|
||||
}
|
||||
t.Log("Create a shared pid sandbox")
|
||||
sb, err := runtimeService.RunPodSandbox(sbConfig, *runtimeHandler)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -35,6 +35,9 @@ import (
|
||||
)
|
||||
|
||||
func TestContainerTTYLeakAfterExit(t *testing.T) {
|
||||
if runtimeHandlerIsRunsc() {
|
||||
t.Skip("runsc uses grouped shims; direct shim socket connection is not supported")
|
||||
}
|
||||
t.Log("Create a sandbox")
|
||||
sb, sbConfig := PodSandboxConfigWithCleanup(t, "sandbox", "container-tty-leak-after-exit")
|
||||
|
||||
|
||||
@@ -154,6 +154,9 @@ func isSwapLikelyEnabled() bool {
|
||||
}
|
||||
|
||||
func TestUpdateContainerResources_MemorySwap(t *testing.T) {
|
||||
if runtimeHandlerIsRunsc() {
|
||||
t.Skip("runsc does not implement cgroup memory swap limits")
|
||||
}
|
||||
if !isSwapLikelyEnabled() {
|
||||
t.Skipf("Swap or swap accounting are not enabled. Swap is required for this test")
|
||||
return
|
||||
@@ -226,6 +229,9 @@ func TestUpdateContainerResources_MemorySwap(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUpdateContainerResources_MemoryLimit(t *testing.T) {
|
||||
if runtimeHandlerIsRunsc() {
|
||||
t.Skip("runsc does not implement cgroup memory limits")
|
||||
}
|
||||
t.Log("Create a sandbox")
|
||||
sb, sbConfig := PodSandboxConfigWithCleanup(t, "sandbox", "update-container-resources")
|
||||
|
||||
@@ -306,6 +312,9 @@ func TestUpdateContainerResources_MemoryLimit(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUpdateContainerResources_StatusUpdated(t *testing.T) {
|
||||
if runtimeHandlerIsRunsc() {
|
||||
t.Skip("runsc does not implement cgroup memory limits")
|
||||
}
|
||||
t.Log("Create a sandbox")
|
||||
sb, sbConfig := PodSandboxConfigWithCleanup(t, "sandbox", "update-container-resources")
|
||||
|
||||
|
||||
@@ -134,6 +134,9 @@ func TestImageVolumeBasic(t *testing.T) {
|
||||
if !selinux.GetEnabled() {
|
||||
t.Skip("SELinux is not enabled")
|
||||
}
|
||||
if runtimeHandlerIsRunsc() {
|
||||
t.Skip("runsc does not support SELinux labels in the OCI spec")
|
||||
}
|
||||
}
|
||||
|
||||
podCtx, cnID, err := setupRunningContainerWithImageVolume(t, tc.selinuxLevel, tc.containerImage, tc.imageVolumeImage, tc.imageSubPath, tc.containerPath)
|
||||
@@ -358,6 +361,9 @@ func TestImageVolumeSetupIfContainerdRestarts(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestImageVolumeWithUserNamespace(t *testing.T) {
|
||||
if runtimeHandlerIsRunsc() {
|
||||
t.Skip("runsc does not support host user namespaces")
|
||||
}
|
||||
// Check if user namespace and idmap are supported
|
||||
if !supportsUserNS() {
|
||||
t.Skip("user namespace not supported")
|
||||
|
||||
@@ -43,6 +43,9 @@ import (
|
||||
//
|
||||
// NOTE: https://github.com/containerd/containerd/issues/8931 is the same issue.
|
||||
func TestIssue7496(t *testing.T) {
|
||||
if runtimeHandlerIsRunsc() {
|
||||
t.Skip("runsc does not use host umount2; strace injection does not apply")
|
||||
}
|
||||
ctx := namespaces.WithNamespace(context.Background(), "k8s.io")
|
||||
|
||||
t.Logf("Create a pod config and run sandbox container")
|
||||
|
||||
@@ -104,6 +104,9 @@ func TestIssue7496_ShouldRetryShutdown(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestKillShimPublishesTaskExitAndDeleteEvents(t *testing.T) {
|
||||
if runtimeHandlerIsRunsc() {
|
||||
t.Skip("runsc uses grouped shims; direct shim socket connection is not supported")
|
||||
}
|
||||
ctx := namespaces.WithNamespace(t.Context(), "k8s.io")
|
||||
|
||||
sbConfig := PodSandboxConfig("sandbox", t.Name(), WithHostNetwork)
|
||||
@@ -156,6 +159,9 @@ func TestKillShimPublishesTaskExitAndDeleteEvents(t *testing.T) {
|
||||
// Regression test for https://github.com/containerd/containerd/issues/13293 (orphaned shim state after shim SIGKILL).
|
||||
// This test asserts that containerd publishes task exit and delete events for a container when the shim disconnects.
|
||||
func TestKillShimPublishesTaskExitAndDeleteEventsForContainer(t *testing.T) {
|
||||
if runtimeHandlerIsRunsc() {
|
||||
t.Skip("runsc uses grouped shims; direct shim socket connection is not supported")
|
||||
}
|
||||
ctx := namespaces.WithNamespace(t.Context(), "k8s.io")
|
||||
|
||||
sbConfig := PodSandboxConfig("sandbox", t.Name(), WithHostNetwork)
|
||||
@@ -429,6 +435,9 @@ func countTaskExitDeleteEventsUntilBarrier(t *testing.T, id, barrierTopic string
|
||||
}
|
||||
|
||||
func TestShutdownShimWhenPauseExitsBeforeWorkload(t *testing.T) {
|
||||
if runtimeHandlerIsRunsc() {
|
||||
t.Skip("runsc uses grouped shims; direct shim socket connection is not supported")
|
||||
}
|
||||
ctx := namespaces.WithNamespace(t.Context(), "k8s.io")
|
||||
|
||||
t.Logf("RunPodSandbox")
|
||||
|
||||
@@ -70,9 +70,22 @@ var (
|
||||
|
||||
var criEndpoint = flag.String("cri-endpoint", "unix:///run/containerd/containerd.sock", "The endpoint of cri plugin.")
|
||||
var runtimeHandler = flag.String("runtime-handler", "", "The runtime handler to use in the test.")
|
||||
var runtimeType = flag.String("runtime-type", "", "The OCI runtime type of the default runtime handler (e.g. io.containerd.runsc.v1).")
|
||||
var containerdBin = flag.String("containerd-bin", "containerd", "The containerd binary name. The name is used to restart containerd during test.")
|
||||
var buildDir = flag.String("build-dir", "", "Build output directory for containerd binaries")
|
||||
|
||||
func runtimeHandlerIsRunsc() bool {
|
||||
if *runtimeType == "io.containerd.runsc.v1" {
|
||||
return true
|
||||
}
|
||||
// Match documented handler name aliases for gVisor / runsc.
|
||||
switch *runtimeHandler {
|
||||
case "runsc", "gvisor":
|
||||
return true
|
||||
}
|
||||
return strings.HasPrefix(*runtimeHandler, "runsc-")
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
flag.Parse()
|
||||
if err := ConnectDaemons(); err != nil {
|
||||
|
||||
@@ -33,6 +33,9 @@ import (
|
||||
|
||||
// Test NRI networking capabilities.
|
||||
func TestNriPluginNetworkingSynchronization(t *testing.T) {
|
||||
if runtimeHandlerIsRunsc() {
|
||||
t.Skip("runsc uses its own netstack; NRI cannot read pod IPs from the host network namespace")
|
||||
}
|
||||
skipNriTestIfNecessary(t)
|
||||
|
||||
t.Log("Test that NRI plugins get pod networking attributes on synchronization.")
|
||||
@@ -107,6 +110,9 @@ func TestNriPluginNetworkingSynchronization(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestNriPluginNetworkingLifecycle(t *testing.T) {
|
||||
if runtimeHandlerIsRunsc() {
|
||||
t.Skip("runsc uses its own netstack; NRI cannot read pod IPs from the host network namespace")
|
||||
}
|
||||
skipNriTestIfNecessary(t)
|
||||
|
||||
t.Log("Test that NRI plugins get pod networking attributes during the pod lifecycle.")
|
||||
|
||||
@@ -303,6 +303,9 @@ func TestNriLinuxDeviceInjection(t *testing.T) {
|
||||
|
||||
// Test linux cpuset adjustment by NRI plugins.
|
||||
func TestNriLinuxCpusetAdjustment(t *testing.T) {
|
||||
if runtimeHandlerIsRunsc() {
|
||||
t.Skip("runsc does not propagate NRI cpuset adjustments to the container's /proc/self/status")
|
||||
}
|
||||
skipNriTestIfNecessary(t,
|
||||
map[string]bool{
|
||||
"not enough online CPUs for test": len(getAvailableCpuset(t)) < 2,
|
||||
@@ -348,6 +351,9 @@ func TestNriLinuxCpusetAdjustment(t *testing.T) {
|
||||
|
||||
// Test linux memset adjustment by NRI plugins.
|
||||
func TestNriLinuxMemsetAdjustment(t *testing.T) {
|
||||
if runtimeHandlerIsRunsc() {
|
||||
t.Skip("runsc does not propagate NRI memset adjustments to the container's /proc/self/status")
|
||||
}
|
||||
skipNriTestIfNecessary(t,
|
||||
map[string]bool{
|
||||
"not enough online memory nodes for test": len(getAvailableMemset(t)) < 2,
|
||||
@@ -393,6 +399,9 @@ func TestNriLinuxMemsetAdjustment(t *testing.T) {
|
||||
|
||||
// Test creation-time linux cpuset update of existing containers by NRI plugins.
|
||||
func TestNriLinuxCpusetAdjustmentUpdate(t *testing.T) {
|
||||
if runtimeHandlerIsRunsc() {
|
||||
t.Skip("runsc does not propagate NRI cpuset adjustments to the container's /proc/self/status")
|
||||
}
|
||||
skipNriTestIfNecessary(t,
|
||||
map[string]bool{
|
||||
"not enough online CPUs for test": len(getAvailableCpuset(t)) < 2,
|
||||
@@ -464,6 +473,9 @@ func TestNriLinuxCpusetAdjustmentUpdate(t *testing.T) {
|
||||
|
||||
// Test creation-time linux memset update of existing containers by NRI plugins.
|
||||
func TestNriLinuxMemsetAdjustmentUpdate(t *testing.T) {
|
||||
if runtimeHandlerIsRunsc() {
|
||||
t.Skip("runsc does not propagate NRI memset adjustments to the container's /proc/self/status")
|
||||
}
|
||||
skipNriTestIfNecessary(t,
|
||||
map[string]bool{
|
||||
"not enough online memory nodes for test": len(getAvailableMemset(t)) < 2,
|
||||
@@ -532,6 +544,9 @@ func TestNriLinuxMemsetAdjustmentUpdate(t *testing.T) {
|
||||
|
||||
// Test pod sandbox updates received by NRI plugins.
|
||||
func TestNriUpdatePodSandbox(t *testing.T) {
|
||||
if runtimeHandlerIsRunsc() {
|
||||
t.Skip("runsc does not implement cgroup memory limits")
|
||||
}
|
||||
skipNriTestIfNecessary(t)
|
||||
|
||||
t.Log("Test that NRI plugins receive pod sandbox updates.")
|
||||
@@ -574,6 +589,9 @@ func TestNriUpdatePodSandbox(t *testing.T) {
|
||||
|
||||
// Test pod sandbox resource updates persist across containerd restarts.
|
||||
func TestUpdatePodSandboxWithRestart(t *testing.T) {
|
||||
if runtimeHandlerIsRunsc() {
|
||||
t.Skip("runsc sandboxes do not survive containerd restart; state recovery is not supported")
|
||||
}
|
||||
skipNriTestIfNecessary(t)
|
||||
|
||||
t.Log("Test that pod sandbox resource updates persist across containerd restarts.")
|
||||
@@ -613,6 +631,9 @@ func TestUpdatePodSandboxWithRestart(t *testing.T) {
|
||||
|
||||
// Test NRI vs. containerd restart.
|
||||
func TestNriPluginContainerdRestart(t *testing.T) {
|
||||
if runtimeHandlerIsRunsc() {
|
||||
t.Skip("runsc sandboxes do not survive containerd restart; state recovery is not supported")
|
||||
}
|
||||
skipNriTestIfNecessary(t)
|
||||
|
||||
t.Log("Test NRI plugins vs. containerd restart.")
|
||||
|
||||
@@ -28,11 +28,13 @@ import (
|
||||
"github.com/containerd/containerd/v2/integration/images"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
criruntime "k8s.io/cri-api/pkg/apis/runtime/v1"
|
||||
runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1"
|
||||
)
|
||||
|
||||
func TestOOMEventMonitor(t *testing.T) {
|
||||
if runtimeHandlerIsRunsc() {
|
||||
t.Skip("runsc does not implement cgroup memory limits; OOMKilled reporting requires host cgroup enforcement")
|
||||
}
|
||||
workDir := t.TempDir()
|
||||
|
||||
rawCfg := fmt.Sprintf(`
|
||||
@@ -96,7 +98,7 @@ version = 3
|
||||
wg.Go(func() {
|
||||
|
||||
cntrID := podCtx.createContainer(fmt.Sprintf("round-%d-running", round), busyboxImage,
|
||||
criruntime.ContainerState_CONTAINER_RUNNING,
|
||||
runtimeapi.ContainerState_CONTAINER_RUNNING,
|
||||
WithCommand(
|
||||
"sh",
|
||||
"-c",
|
||||
@@ -117,7 +119,7 @@ version = 3
|
||||
}
|
||||
|
||||
state := status.GetState()
|
||||
if state != criruntime.ContainerState_CONTAINER_EXITED {
|
||||
if state != runtimeapi.ContainerState_CONTAINER_EXITED {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -65,6 +65,9 @@ func TestPodHostname(t *testing.T) {
|
||||
if test.needsHostNetwork && goruntime.GOOS == "windows" {
|
||||
t.Skip("Skipped on Windows.")
|
||||
}
|
||||
if test.needsHostNetwork && runtimeHandlerIsRunsc() {
|
||||
t.Skip("runsc does not support host network")
|
||||
}
|
||||
testPodLogDir := t.TempDir()
|
||||
|
||||
opts := append(test.opts, WithPodLogDirectory(testPodLogDir))
|
||||
|
||||
@@ -127,6 +127,9 @@ func traversePath(tPath string) error {
|
||||
}
|
||||
|
||||
func TestPodUserNS(t *testing.T) {
|
||||
if runtimeHandlerIsRunsc() {
|
||||
t.Skip("runsc does not support host user namespaces")
|
||||
}
|
||||
containerID := uint32(0)
|
||||
hostID := uint32(65536)
|
||||
size := uint32(65536)
|
||||
@@ -350,6 +353,9 @@ func TestPodUserNS(t *testing.T) {
|
||||
// [1]: https://github.com/containerd/containerd/issues/10598
|
||||
// [2]: https://github.com/anakryiko/retsnoop
|
||||
func TestIssue10598(t *testing.T) {
|
||||
if runtimeHandlerIsRunsc() {
|
||||
t.Skip("runsc does not support host user namespaces")
|
||||
}
|
||||
if !supportsUserNS() {
|
||||
t.Skip("User namespaces are not supported")
|
||||
}
|
||||
@@ -447,6 +453,9 @@ func TestIssue10598(t *testing.T) {
|
||||
//
|
||||
// https://github.com/containerd/containerd/issues/11852
|
||||
func TestUsernsVolumeCopyUp(t *testing.T) {
|
||||
if runtimeHandlerIsRunsc() {
|
||||
t.Skip("runsc does not support host user namespaces")
|
||||
}
|
||||
if !supportsUserNS() {
|
||||
t.Skip("User namespaces are not supported")
|
||||
}
|
||||
|
||||
@@ -30,6 +30,9 @@ import (
|
||||
)
|
||||
|
||||
func TestContainerdRestartSandboxRecover(t *testing.T) {
|
||||
if runtimeHandlerIsRunsc() {
|
||||
t.Skip("runsc sandboxes do not survive containerd restart; state recovery is not supported")
|
||||
}
|
||||
sbStatuses := map[string]runtime.PodSandboxState{
|
||||
// Sandbox with unknown status will be NotReady when returned from ListPodSandbox
|
||||
"sandbox_unknown": runtime.PodSandboxState_SANDBOX_NOTREADY,
|
||||
|
||||
@@ -34,6 +34,9 @@ import (
|
||||
// Restart test must run sequentially.
|
||||
|
||||
func TestContainerdRestart(t *testing.T) {
|
||||
if runtimeHandlerIsRunsc() {
|
||||
t.Skip("runsc sandboxes do not survive containerd restart; state recovery is not supported")
|
||||
}
|
||||
type container struct {
|
||||
name string
|
||||
id string
|
||||
|
||||
@@ -73,8 +73,11 @@ func TestTruncIndex(t *testing.T) {
|
||||
assert.Equal(t, sb, sbStatus.Id)
|
||||
|
||||
t.Logf("Forward port for sandbox by truncindex")
|
||||
_, err = runtimeService.PortForward(&runtimeapi.PortForwardRequest{PodSandboxId: sbTruncIndex, Port: []int32{80}})
|
||||
assert.NoError(t, err)
|
||||
if !runtimeHandlerIsRunsc() {
|
||||
// runsc does not support port-forwarding into its own network namespace.
|
||||
_, err = runtimeService.PortForward(&runtimeapi.PortForwardRequest{PodSandboxId: sbTruncIndex, Port: []int32{80}})
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
// TODO(yanxuean): add test case for ListPodSandbox
|
||||
|
||||
@@ -108,21 +111,27 @@ func TestTruncIndex(t *testing.T) {
|
||||
}()
|
||||
|
||||
t.Logf("Stats the container")
|
||||
cStats, err := runtimeService.ContainerStats(cnTruncIndex)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, cn, cStats.Attributes.Id)
|
||||
if !runtimeHandlerIsRunsc() {
|
||||
// runsc does not expose per-container stats.
|
||||
cStats, err := runtimeService.ContainerStats(cnTruncIndex)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, cn, cStats.Attributes.Id)
|
||||
}
|
||||
|
||||
t.Logf("Update container memory limit after started")
|
||||
if goruntime.GOOS != "windows" {
|
||||
err = runtimeService.UpdateContainerResources(cnTruncIndex, &runtimeapi.LinuxContainerResources{
|
||||
MemoryLimitInBytes: 50 * 1024 * 1024,
|
||||
}, nil)
|
||||
assert.NoError(t, err)
|
||||
} else {
|
||||
err = runtimeService.UpdateContainerResources(cnTruncIndex, nil, &runtimeapi.WindowsContainerResources{
|
||||
MemoryLimitInBytes: 50 * 1024 * 1024,
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
if !runtimeHandlerIsRunsc() {
|
||||
// runsc does not implement cgroup memory limits.
|
||||
if goruntime.GOOS != "windows" {
|
||||
err = runtimeService.UpdateContainerResources(cnTruncIndex, &runtimeapi.LinuxContainerResources{
|
||||
MemoryLimitInBytes: 50 * 1024 * 1024,
|
||||
}, nil)
|
||||
assert.NoError(t, err)
|
||||
} else {
|
||||
err = runtimeService.UpdateContainerResources(cnTruncIndex, nil, &runtimeapi.WindowsContainerResources{
|
||||
MemoryLimitInBytes: 50 * 1024 * 1024,
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
}
|
||||
|
||||
t.Logf("Execute cmd in container")
|
||||
|
||||
@@ -18,12 +18,16 @@ package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"sort"
|
||||
"strconv"
|
||||
|
||||
runcoptions "github.com/containerd/containerd/api/types/runc/options"
|
||||
runtimeoptions "github.com/containerd/containerd/api/types/runtimeoptions/v1"
|
||||
criconfig "github.com/containerd/containerd/v2/internal/cri/config"
|
||||
"github.com/containerd/containerd/v2/internal/cri/systemd"
|
||||
"github.com/containerd/log"
|
||||
"github.com/pelletier/go-toml/v2"
|
||||
runtime "k8s.io/cri-api/pkg/apis/runtime/v1"
|
||||
)
|
||||
|
||||
@@ -72,11 +76,60 @@ func (c *criService) getCgroupDriver(ctx context.Context) runtime.CgroupDriver {
|
||||
func getCgroupDriverFromRuntimeHandlerOpts(opts any) (runtime.CgroupDriver, bool) {
|
||||
switch v := opts.(type) {
|
||||
case *runcoptions.Options:
|
||||
systemdCgroup := v.SystemdCgroup
|
||||
if systemdCgroup {
|
||||
if v.SystemdCgroup {
|
||||
return runtime.CgroupDriver_SYSTEMD, true
|
||||
}
|
||||
return runtime.CgroupDriver_CGROUPFS, true
|
||||
case *runtimeoptions.Options:
|
||||
// Generic shims (e.g. io.containerd.runsc.v1) carry their config
|
||||
// via a path to a config file or inline via ConfigBody.
|
||||
// We look for a top-level SystemdCgroup key or [runsc_config].systemd-cgroup.
|
||||
// Only return a driver when the key is explicitly present.
|
||||
var data []byte
|
||||
var err error
|
||||
if v.ConfigPath != "" {
|
||||
data, err = os.ReadFile(v.ConfigPath)
|
||||
} else {
|
||||
data = v.ConfigBody
|
||||
}
|
||||
if err != nil || len(data) == 0 {
|
||||
return runtime.CgroupDriver_CGROUPFS, false
|
||||
}
|
||||
|
||||
var cfg struct {
|
||||
SystemdCgroup *bool `toml:"SystemdCgroup"`
|
||||
RunscConfig map[string]any `toml:"runsc_config"`
|
||||
}
|
||||
if err := toml.Unmarshal(data, &cfg); err != nil {
|
||||
return runtime.CgroupDriver_CGROUPFS, false
|
||||
}
|
||||
|
||||
if cfg.SystemdCgroup != nil {
|
||||
if *cfg.SystemdCgroup {
|
||||
return runtime.CgroupDriver_SYSTEMD, true
|
||||
}
|
||||
return runtime.CgroupDriver_CGROUPFS, true
|
||||
}
|
||||
|
||||
// The runsc shim stores the cgroup driver under [runsc_config].systemd-cgroup.
|
||||
// containerd-shim-runsc-v1 expects this value as a TOML string ("true"/"false")
|
||||
// because its config struct maps the field to a Go string; accept both forms.
|
||||
if val, ok := cfg.RunscConfig["systemd-cgroup"]; ok {
|
||||
switch v := val.(type) {
|
||||
case bool:
|
||||
if v {
|
||||
return runtime.CgroupDriver_SYSTEMD, true
|
||||
}
|
||||
return runtime.CgroupDriver_CGROUPFS, true
|
||||
case string:
|
||||
if b, err := strconv.ParseBool(v); err == nil {
|
||||
if b {
|
||||
return runtime.CgroupDriver_SYSTEMD, true
|
||||
}
|
||||
return runtime.CgroupDriver_CGROUPFS, true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return runtime.CgroupDriver_SYSTEMD, false
|
||||
return runtime.CgroupDriver_CGROUPFS, false
|
||||
}
|
||||
@@ -18,6 +18,8 @@ package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
criconfig "github.com/containerd/containerd/v2/internal/cri/config"
|
||||
@@ -38,6 +40,56 @@ func newFakeRuntimeConfig(runcV2, systemdCgroup bool) criconfig.Runtime {
|
||||
return r
|
||||
}
|
||||
|
||||
// newFakeGenericConfigPathRuntime returns a runtime config for a generic shim
|
||||
// that points ConfigPath to a temporary config file with SystemdCgroup set.
|
||||
func newFakeGenericConfigPathRuntime(t *testing.T, runtimeType string, systemdCgroup bool) criconfig.Runtime {
|
||||
t.Helper()
|
||||
val := "false"
|
||||
if systemdCgroup {
|
||||
val = "true"
|
||||
}
|
||||
content := "SystemdCgroup = " + val + "\n"
|
||||
f := filepath.Join(t.TempDir(), "config.toml")
|
||||
if err := os.WriteFile(f, []byte(content), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return criconfig.Runtime{Type: runtimeType, Options: map[string]any{
|
||||
"ConfigPath": f,
|
||||
}}
|
||||
}
|
||||
|
||||
// newFakeRunscConfigPathRuntime returns a runtime config for the runsc shim
|
||||
// that uses config_path to point at a temporary shim config file. The file
|
||||
// uses the [runsc_config] section format that containerd-shim-runsc-v1 reads.
|
||||
// tomlString controls whether systemd-cgroup is written as a TOML string
|
||||
// ("true"/"false") — as produced by write-runsc-shim-config.sh — or as a
|
||||
// bare TOML boolean (true/false).
|
||||
func newFakeRunscConfigPathRuntime(t *testing.T, runtimeType string, systemdCgroup bool, tomlString bool) criconfig.Runtime {
|
||||
t.Helper()
|
||||
var val string
|
||||
if tomlString {
|
||||
if systemdCgroup {
|
||||
val = `"true"`
|
||||
} else {
|
||||
val = `"false"`
|
||||
}
|
||||
} else {
|
||||
if systemdCgroup {
|
||||
val = "true"
|
||||
} else {
|
||||
val = "false"
|
||||
}
|
||||
}
|
||||
content := "[runsc_config]\n systemd-cgroup = " + val + "\n"
|
||||
f := filepath.Join(t.TempDir(), "config.toml")
|
||||
if err := os.WriteFile(f, []byte(content), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return criconfig.Runtime{Type: runtimeType, Options: map[string]any{
|
||||
"ConfigPath": f,
|
||||
}}
|
||||
}
|
||||
|
||||
func TestRuntimeConfig(t *testing.T) {
|
||||
autoDetected := runtime.CgroupDriver_CGROUPFS
|
||||
if systemd.IsRunningSystemd() {
|
||||
@@ -90,6 +142,64 @@ func TestRuntimeConfig(t *testing.T) {
|
||||
},
|
||||
expectedCgroupDriver: runtime.CgroupDriver_SYSTEMD,
|
||||
},
|
||||
{
|
||||
// A generic shim with non-empty options and no ConfigPath must
|
||||
// fall through to host auto-detection, not be silently treated as cgroupfs.
|
||||
desc: "generic shim without ConfigPath falls through to auto-detect",
|
||||
defaultRuntime: "other",
|
||||
runtimes: map[string]criconfig.Runtime{
|
||||
"other": {Type: "io.containerd.other.v1", Options: map[string]any{"SomeOtherKey": "value"}},
|
||||
},
|
||||
expectedCgroupDriver: autoDetected,
|
||||
},
|
||||
{
|
||||
desc: "generic shim with inline SystemdCgroup false",
|
||||
defaultRuntime: "generic",
|
||||
runtimes: map[string]criconfig.Runtime{
|
||||
"generic": {Type: "io.containerd.generic.v1", Options: map[string]any{"SystemdCgroup": false}},
|
||||
},
|
||||
expectedCgroupDriver: runtime.CgroupDriver_CGROUPFS,
|
||||
},
|
||||
{
|
||||
desc: "generic shim with inline SystemdCgroup true",
|
||||
defaultRuntime: "generic",
|
||||
runtimes: map[string]criconfig.Runtime{
|
||||
"generic": {Type: "io.containerd.generic.v1", Options: map[string]any{"SystemdCgroup": true}},
|
||||
},
|
||||
expectedCgroupDriver: runtime.CgroupDriver_SYSTEMD,
|
||||
},
|
||||
{
|
||||
desc: "runsc shim with inline runsc_config systemd-cgroup bool true",
|
||||
defaultRuntime: "runsc",
|
||||
runtimes: map[string]criconfig.Runtime{
|
||||
"runsc": {Type: "io.containerd.runsc.v1", Options: map[string]any{"runsc_config": map[string]any{"systemd-cgroup": true}}},
|
||||
},
|
||||
expectedCgroupDriver: runtime.CgroupDriver_SYSTEMD,
|
||||
},
|
||||
{
|
||||
desc: "runsc shim with inline runsc_config systemd-cgroup bool false",
|
||||
defaultRuntime: "runsc",
|
||||
runtimes: map[string]criconfig.Runtime{
|
||||
"runsc": {Type: "io.containerd.runsc.v1", Options: map[string]any{"runsc_config": map[string]any{"systemd-cgroup": false}}},
|
||||
},
|
||||
expectedCgroupDriver: runtime.CgroupDriver_CGROUPFS,
|
||||
},
|
||||
{
|
||||
desc: "runsc shim with inline runsc_config systemd-cgroup string true",
|
||||
defaultRuntime: "runsc",
|
||||
runtimes: map[string]criconfig.Runtime{
|
||||
"runsc": {Type: "io.containerd.runsc.v1", Options: map[string]any{"runsc_config": map[string]any{"systemd-cgroup": "true"}}},
|
||||
},
|
||||
expectedCgroupDriver: runtime.CgroupDriver_SYSTEMD,
|
||||
},
|
||||
{
|
||||
desc: "runsc shim with inline runsc_config systemd-cgroup string false",
|
||||
defaultRuntime: "runsc",
|
||||
runtimes: map[string]criconfig.Runtime{
|
||||
"runsc": {Type: "io.containerd.runsc.v1", Options: map[string]any{"runsc_config": map[string]any{"systemd-cgroup": "false"}}},
|
||||
},
|
||||
expectedCgroupDriver: runtime.CgroupDriver_CGROUPFS,
|
||||
},
|
||||
} {
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
c := newTestCRIService()
|
||||
@@ -101,4 +211,98 @@ func TestRuntimeConfig(t *testing.T) {
|
||||
assert.Equal(t, test.expectedCgroupDriver, resp.Linux.CgroupDriver, "got unexpected cgroup driver")
|
||||
})
|
||||
}
|
||||
|
||||
// ConfigPath cases use temp files so cannot be in the table above.
|
||||
t.Run("generic config_path, cgroupfs", func(t *testing.T) {
|
||||
c := newTestCRIService()
|
||||
c.config.RuntimeConfig.ContainerdConfig.DefaultRuntimeName = "generic"
|
||||
c.config.RuntimeConfig.ContainerdConfig.Runtimes = map[string]criconfig.Runtime{
|
||||
"generic": newFakeGenericConfigPathRuntime(t, "io.containerd.generic.v1", false),
|
||||
}
|
||||
resp, err := c.RuntimeConfig(context.TODO(), &runtime.RuntimeConfigRequest{})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, runtime.CgroupDriver_CGROUPFS, resp.Linux.CgroupDriver, "got unexpected cgroup driver")
|
||||
})
|
||||
|
||||
t.Run("generic config_path, systemd", func(t *testing.T) {
|
||||
c := newTestCRIService()
|
||||
c.config.RuntimeConfig.ContainerdConfig.DefaultRuntimeName = "generic"
|
||||
c.config.RuntimeConfig.ContainerdConfig.Runtimes = map[string]criconfig.Runtime{
|
||||
"generic": newFakeGenericConfigPathRuntime(t, "io.containerd.generic.v1", true),
|
||||
}
|
||||
resp, err := c.RuntimeConfig(context.TODO(), &runtime.RuntimeConfigRequest{})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, runtime.CgroupDriver_SYSTEMD, resp.Linux.CgroupDriver, "got unexpected cgroup driver")
|
||||
})
|
||||
|
||||
t.Run("generic config_path default overrides runc", func(t *testing.T) {
|
||||
c := newTestCRIService()
|
||||
c.config.RuntimeConfig.ContainerdConfig.DefaultRuntimeName = "generic"
|
||||
c.config.RuntimeConfig.ContainerdConfig.Runtimes = map[string]criconfig.Runtime{
|
||||
"runc": newFakeRuntimeConfig(true, true),
|
||||
"generic": newFakeGenericConfigPathRuntime(t, "io.containerd.generic.v1", false),
|
||||
}
|
||||
resp, err := c.RuntimeConfig(context.TODO(), &runtime.RuntimeConfigRequest{})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, runtime.CgroupDriver_CGROUPFS, resp.Linux.CgroupDriver, "got unexpected cgroup driver")
|
||||
})
|
||||
// Test both the bare-boolean form and the TOML-string form ("true"/"false")
|
||||
// produced by write-runsc-shim-config.sh, since the shim config struct maps
|
||||
// systemd-cgroup to a Go string.
|
||||
t.Run("runsc config_path, cgroupfs (bool)", func(t *testing.T) {
|
||||
c := newTestCRIService()
|
||||
c.config.RuntimeConfig.ContainerdConfig.DefaultRuntimeName = "runsc"
|
||||
c.config.RuntimeConfig.ContainerdConfig.Runtimes = map[string]criconfig.Runtime{
|
||||
"runsc": newFakeRunscConfigPathRuntime(t, "io.containerd.runsc.v1", false, false),
|
||||
}
|
||||
resp, err := c.RuntimeConfig(context.TODO(), &runtime.RuntimeConfigRequest{})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, runtime.CgroupDriver_CGROUPFS, resp.Linux.CgroupDriver, "got unexpected cgroup driver")
|
||||
})
|
||||
|
||||
t.Run("runsc config_path, systemd (bool)", func(t *testing.T) {
|
||||
c := newTestCRIService()
|
||||
c.config.RuntimeConfig.ContainerdConfig.DefaultRuntimeName = "runsc"
|
||||
c.config.RuntimeConfig.ContainerdConfig.Runtimes = map[string]criconfig.Runtime{
|
||||
"runsc": newFakeRunscConfigPathRuntime(t, "io.containerd.runsc.v1", true, false),
|
||||
}
|
||||
resp, err := c.RuntimeConfig(context.TODO(), &runtime.RuntimeConfigRequest{})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, runtime.CgroupDriver_SYSTEMD, resp.Linux.CgroupDriver, "got unexpected cgroup driver")
|
||||
})
|
||||
|
||||
t.Run("runsc config_path, cgroupfs (string)", func(t *testing.T) {
|
||||
c := newTestCRIService()
|
||||
c.config.RuntimeConfig.ContainerdConfig.DefaultRuntimeName = "runsc"
|
||||
c.config.RuntimeConfig.ContainerdConfig.Runtimes = map[string]criconfig.Runtime{
|
||||
"runsc": newFakeRunscConfigPathRuntime(t, "io.containerd.runsc.v1", false, true),
|
||||
}
|
||||
resp, err := c.RuntimeConfig(context.TODO(), &runtime.RuntimeConfigRequest{})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, runtime.CgroupDriver_CGROUPFS, resp.Linux.CgroupDriver, "got unexpected cgroup driver")
|
||||
})
|
||||
|
||||
t.Run("runsc config_path, systemd (string)", func(t *testing.T) {
|
||||
c := newTestCRIService()
|
||||
c.config.RuntimeConfig.ContainerdConfig.DefaultRuntimeName = "runsc"
|
||||
c.config.RuntimeConfig.ContainerdConfig.Runtimes = map[string]criconfig.Runtime{
|
||||
"runsc": newFakeRunscConfigPathRuntime(t, "io.containerd.runsc.v1", true, true),
|
||||
}
|
||||
resp, err := c.RuntimeConfig(context.TODO(), &runtime.RuntimeConfigRequest{})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, runtime.CgroupDriver_SYSTEMD, resp.Linux.CgroupDriver, "got unexpected cgroup driver")
|
||||
})
|
||||
|
||||
t.Run("runsc config_path missing file falls through to auto-detect", func(t *testing.T) {
|
||||
c := newTestCRIService()
|
||||
c.config.RuntimeConfig.ContainerdConfig.DefaultRuntimeName = "runsc"
|
||||
c.config.RuntimeConfig.ContainerdConfig.Runtimes = map[string]criconfig.Runtime{
|
||||
"runsc": {Type: "io.containerd.runsc.v1", Options: map[string]any{
|
||||
"ConfigPath": "/nonexistent/runsc/config.toml",
|
||||
}},
|
||||
}
|
||||
resp, err := c.RuntimeConfig(context.TODO(), &runtime.RuntimeConfigRequest{})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, autoDetected, resp.Linux.CgroupDriver, "got unexpected cgroup driver")
|
||||
})
|
||||
}
|
||||
@@ -238,22 +238,22 @@ func migrateConfig(dst, src map[string]any) {
|
||||
}
|
||||
|
||||
var runtimePlatforms map[string]any
|
||||
if v, ok := dst["runtime_platform"]; ok {
|
||||
if v, ok := dst["runtime_platforms"]; ok {
|
||||
runtimePlatforms = v.(map[string]any)
|
||||
} else {
|
||||
runtimePlatforms = map[string]any{}
|
||||
}
|
||||
for runtime, v := range runtimesConf.(map[string]any) {
|
||||
runtimeConf := v.(map[string]any)
|
||||
if snapshotter, ok := runtimeConf["snapshot"]; ok && snapshotter != "" {
|
||||
if snapshotter, ok := runtimeConf["snapshotter"]; ok && snapshotter != "" {
|
||||
runtimePlatforms[runtime] = map[string]any{
|
||||
"platform": platforms.DefaultStrict(),
|
||||
"platform": platforms.DefaultString(),
|
||||
"snapshotter": snapshotter,
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(runtimePlatforms) > 0 {
|
||||
dst["runtime_platform"] = runtimePlatforms
|
||||
dst["runtime_platforms"] = runtimePlatforms
|
||||
}
|
||||
|
||||
for _, key := range []string{
|
||||
|
||||
@@ -20,9 +20,11 @@ import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/containerd/containerd/v2/plugins"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/containerd/containerd/v2/plugins"
|
||||
)
|
||||
|
||||
func TestSandboxImageConfigMigration(t *testing.T) {
|
||||
@@ -68,3 +70,42 @@ func TestRegistryConfigMigration(t *testing.T) {
|
||||
configPath := v.(string)
|
||||
assert.Equal(t, path, configPath)
|
||||
}
|
||||
|
||||
func TestRuntimePlatformsConfigMigration(t *testing.T) {
|
||||
snapshotter := "devmapper"
|
||||
grpcCri := map[string]any{
|
||||
"containerd": map[string]any{
|
||||
"runtimes": map[string]any{
|
||||
"kata": map[string]any{
|
||||
// Old per-runtime snapshotter key is "snapshotter", not "snapshot".
|
||||
"snapshotter": snapshotter,
|
||||
},
|
||||
// Runtime with no snapshotter should not appear in runtime_platforms.
|
||||
"runc": map[string]any{},
|
||||
},
|
||||
},
|
||||
}
|
||||
pluginConfigs := map[string]any{
|
||||
string(plugins.GRPCPlugin) + ".cri": grpcCri,
|
||||
}
|
||||
configMigration(context.Background(), 2, pluginConfigs)
|
||||
|
||||
v, ok := pluginConfigs[string(plugins.CRIServicePlugin)+".images"]
|
||||
require.True(t, ok)
|
||||
images := v.(map[string]any)
|
||||
|
||||
// The destination key is "runtime_platforms" (plural), matching the TOML
|
||||
// tag on ImageConfig.RuntimePlatforms.
|
||||
v, ok = images["runtime_platforms"]
|
||||
require.True(t, ok, "runtime_platforms key must be present after migration")
|
||||
runtimePlatforms := v.(map[string]any)
|
||||
|
||||
kata, ok := runtimePlatforms["kata"]
|
||||
require.True(t, ok, "kata runtime must be present in runtime_platforms")
|
||||
kataConf := kata.(map[string]any)
|
||||
assert.Equal(t, platforms.DefaultString(), kataConf["platform"])
|
||||
assert.Equal(t, snapshotter, kataConf["snapshotter"])
|
||||
|
||||
_, ok = runtimePlatforms["runc"]
|
||||
assert.False(t, ok, "runc has no snapshotter and must not appear in runtime_platforms")
|
||||
}
|
||||
+20
-8
@@ -50,7 +50,9 @@ function cleanup() {
|
||||
trap cleanup EXIT
|
||||
|
||||
mkdir -p ${BDIR}/{root,state}
|
||||
cat > ${BDIR}/config.toml <<EOF
|
||||
containerd_config="${CONTAINERD_CONFIG_FILE:-${BDIR}/config.toml}"
|
||||
if [[ -z "${CONTAINERD_CONFIG_FILE:-}" ]]; then
|
||||
cat > "${containerd_config}" <<EOF
|
||||
version = 2
|
||||
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
|
||||
runtime_type = "${TEST_RUNTIME}"
|
||||
@@ -63,11 +65,15 @@ runtime_type = "${TEST_RUNTIME}"
|
||||
slow_chown = true
|
||||
EOF
|
||||
|
||||
if [ ! -z "$CGROUP_DRIVER" ] && [ "$CGROUP_DRIVER" = "systemd" ];then
|
||||
cat >> ${BDIR}/config.toml <<EOF
|
||||
if [ ! -z "$CGROUP_DRIVER" ] && [ "$CGROUP_DRIVER" = "systemd" ];then
|
||||
cat >> "${containerd_config}" <<EOF
|
||||
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
|
||||
SystemdCgroup = true
|
||||
EOF
|
||||
fi
|
||||
elif [[ ! -f "${containerd_config}" ]]; then
|
||||
echo "containerd config ${containerd_config} does not exist" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
GINKGO_SKIP_TEST=()
|
||||
@@ -120,15 +126,21 @@ ls /etc/cni/net.d
|
||||
|
||||
/usr/local/bin/containerd \
|
||||
-a ${BDIR}/c.sock \
|
||||
--config ${BDIR}/config.toml \
|
||||
--config "${containerd_config}" \
|
||||
--root ${BDIR}/root \
|
||||
--state ${BDIR}/state \
|
||||
--log-level debug &> "$report_dir/containerd.log" &
|
||||
|
||||
# Make sure containerd is ready before calling critest.
|
||||
for i in $(seq 1 10)
|
||||
do
|
||||
crictl --runtime-endpoint ${BDIR}/c.sock info && break || sleep 1
|
||||
for i in $(seq 1 10); do
|
||||
crictl --runtime-endpoint ${BDIR}/c.sock info 2>/dev/null && break
|
||||
if [[ "${i}" -eq 10 ]]; then
|
||||
echo "containerd did not become ready after 10 seconds" >&2
|
||||
exit 1
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
critest --report-dir "$report_dir" --runtime-endpoint=unix:///${BDIR}/c.sock --parallel=8 "${GINKGO_SKIP_TEST[@]}" "${GINKGO_FOCUS_TEST[@]}" ${EXTRA_CRITEST_OPTIONS:-}
|
||||
ginkgo_procs="${GINKGO_NODES:-8}"
|
||||
|
||||
critest --report-dir "$report_dir" --runtime-endpoint=unix:///${BDIR}/c.sock --parallel="${ginkgo_procs}" "${GINKGO_SKIP_TEST[@]}" "${GINKGO_FOCUS_TEST[@]}" ${EXTRA_CRITEST_OPTIONS:-}
|
||||
Executable
+47
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright The containerd Authors.
|
||||
|
||||
# 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.
|
||||
|
||||
#
|
||||
# Writes a complete /etc/containerd/config.toml for a runsc (gVisor) setup,
|
||||
# replacing any existing config. This avoids fragile in-place patching of the
|
||||
# file written by script/setup/config-containerd.
|
||||
#
|
||||
# Required environment variable:
|
||||
# CGROUP_DRIVER — must be either "cgroupfs" or "systemd"
|
||||
#
|
||||
set -eux -o pipefail
|
||||
|
||||
: "${CGROUP_DRIVER:?CGROUP_DRIVER must be set to cgroupfs or systemd}"
|
||||
|
||||
script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" > /dev/null 2>&1; pwd -P)"
|
||||
|
||||
SUDO=''
|
||||
if [[ "$(id -u)" != "0" ]]; then
|
||||
SUDO='sudo'
|
||||
fi
|
||||
|
||||
${SUDO} mkdir -p /etc/containerd
|
||||
|
||||
# Delegate to the shared helper so the config is defined in one place.
|
||||
tmpfile="$(mktemp /tmp/containerd-config-runsc-XXXXXX.toml)"
|
||||
trap 'rm -f "${tmpfile}"' EXIT
|
||||
"${script_dir}/write-containerd-runsc-config.sh" "${tmpfile}" "${CGROUP_DRIVER}"
|
||||
${SUDO} cp "${tmpfile}" /etc/containerd/config.toml
|
||||
|
||||
# Write the runsc shim config file. write-runsc-shim-config.sh removes the
|
||||
# higher-precedence /run/containerd/runsc/config.toml before writing to /etc,
|
||||
# so stale files from previous runs cannot override the requested settings.
|
||||
"${script_dir}/write-runsc-shim-config.sh" "${CGROUP_DRIVER}"
|
||||
Executable
+99
@@ -0,0 +1,99 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright The containerd Authors.
|
||||
|
||||
# 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.
|
||||
|
||||
#
|
||||
# Runs critest against a containerd instance configured for runsc (gVisor).
|
||||
# Skips tests for features that gVisor does not support.
|
||||
#
|
||||
# Usage: critest-runsc.sh <report_dir>
|
||||
#
|
||||
# Required environment variable:
|
||||
# CGROUP_DRIVER — must be either "cgroupfs" or "systemd"
|
||||
#
|
||||
# The containerd and runsc shim configs must already be written by the caller.
|
||||
# Pass the containerd config through CONTAINERD_CONFIG_FILE.
|
||||
#
|
||||
set -eu -o pipefail
|
||||
|
||||
report_dir=${1:?report_dir argument is required}
|
||||
|
||||
: "${CGROUP_DRIVER:?CGROUP_DRIVER must be set to cgroupfs or systemd}"
|
||||
: "${CONTAINERD_CONFIG_FILE:?CONTAINERD_CONFIG_FILE must point to the runsc containerd config}"
|
||||
|
||||
script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" > /dev/null 2>&1; pwd -P)"
|
||||
|
||||
# Fail fast if a runsc sandbox remains before critest. The root directory itself
|
||||
# may remain because runsc keeps its shared null network namespace there.
|
||||
_runsc_root=/run/containerd-runsc-test
|
||||
if [[ -e "${_runsc_root}" ]]; then
|
||||
if ! _runsc_ids="$(runsc --root="${_runsc_root}" list --quiet)"; then
|
||||
echo "ERROR: unable to inspect runsc root ${_runsc_root}" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ -n "${_runsc_ids}" ]]; then
|
||||
echo "ERROR: stale runsc sandboxes found in ${_runsc_root}:" >&2
|
||||
echo "${_runsc_ids}" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Skip tests for features gVisor does not support.
|
||||
# See script/vm/test-cri.sh for the full rationale.
|
||||
skip_tests=(
|
||||
'HostIpc is true'
|
||||
'HostNetwork is true'
|
||||
'HostPID'
|
||||
'SELinux'
|
||||
'should support safe sysctls'
|
||||
'should support unsafe sysctls'
|
||||
'mount propagation'
|
||||
'rshared'
|
||||
'non-recursive readonly'
|
||||
'adding capability'
|
||||
'MaskedPaths'
|
||||
'ReadonlyPaths'
|
||||
'SeccompProfilePath'
|
||||
'UserNamespaces'
|
||||
'portforward'
|
||||
'listing pod sandbox metrics'
|
||||
'listing container stats|listing stats for'
|
||||
'should enforce a apparmor_profile blocking writes'
|
||||
'should allow privilege escalation when false'
|
||||
'runtime should support Privileged is true'
|
||||
)
|
||||
# Skip OOM tests for runsc entirely - it intentionally triggers container OOM
|
||||
# kills which causes host memory pressure on CI runners (both cgroupfs and systemd).
|
||||
skip_tests+=(
|
||||
'should terminate with exitCode 137'
|
||||
'OOMKilled'
|
||||
)
|
||||
skip_arg=$(IFS='|'; echo "${skip_tests[*]}")
|
||||
|
||||
if [[ -n "${SKIP_TEST:-}" ]]; then
|
||||
SKIP_TEST="${SKIP_TEST}|${skip_arg}"
|
||||
else
|
||||
SKIP_TEST="${skip_arg}"
|
||||
fi
|
||||
export SKIP_TEST
|
||||
|
||||
if [[ -z "${GINKGO_NODES:-}" ]]; then
|
||||
# Cap default parallelism to avoid host resource exhaustion on high-core runners.
|
||||
_procs=$(($(nproc) + 2))
|
||||
GINKGO_NODES=$(( _procs > 8 ? 8 : _procs ))
|
||||
fi
|
||||
export GINKGO_NODES
|
||||
|
||||
exec "${script_dir}/../critest.sh" "${report_dir}"
|
||||
Executable
+69
@@ -0,0 +1,69 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright The containerd Authors.
|
||||
|
||||
# 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.
|
||||
|
||||
#
|
||||
# Downloads and installs runsc (gVisor) and containerd-shim-runsc-v1
|
||||
# from the official gVisor GCS release bucket.
|
||||
# The version is read from script/runsc/runsc-version or overridden via $RUNSC_VERSION.
|
||||
#
|
||||
set -eu -o pipefail
|
||||
|
||||
script_dir="$(cd -- "$(dirname -- "$0")" > /dev/null 2>&1; pwd -P)"
|
||||
|
||||
# e2e and Cirrus will fail with "sudo: command not found"
|
||||
SUDO=''
|
||||
if [[ "$(id -u)" != "0" ]]; then
|
||||
SUDO='sudo'
|
||||
fi
|
||||
|
||||
: "${RUNSC_VERSION:=$(cat "${script_dir}/runsc-version")}"
|
||||
: "${RUNSC_REPO:=https://storage.googleapis.com/gvisor/releases/release}"
|
||||
|
||||
# GCS uses Linux arch names (x86_64/aarch64), not Go arch names (amd64/arm64)
|
||||
case "$(uname -m)" in
|
||||
x86_64|aarch64) ARCH="$(uname -m)" ;;
|
||||
amd64) ARCH="x86_64" ;;
|
||||
arm64) ARCH="aarch64" ;;
|
||||
*) echo >&2 "unsupported arch for runsc: $(uname -m)"; exit 1 ;;
|
||||
esac
|
||||
|
||||
# Download the release tarball (includes runsc, containerd-shim-runsc-v1, and
|
||||
# the required gvisor-bin/ sidecar executables) and verify its checksum.
|
||||
tarball="$(mktemp /tmp/gvisor-XXXXXX.tar.bz2)"
|
||||
tmpdir="$(mktemp -d /tmp/gvisor-XXXXXX)"
|
||||
trap 'rm -rf "${tmpdir}" "${tarball}"' EXIT
|
||||
|
||||
curl -fsSL --retry 5 -o "${tarball}" \
|
||||
"${RUNSC_REPO}/${RUNSC_VERSION}/${ARCH}/gvisor.tar.bz2"
|
||||
|
||||
# Verify the sha512 checksum published alongside the tarball.
|
||||
expected_sha512="$(curl -fsSL --retry 5 "${RUNSC_REPO}/${RUNSC_VERSION}/${ARCH}/gvisor.tar.bz2.sha512" | awk '{print $1}')"
|
||||
actual_sha512="$(sha512sum "${tarball}" | awk '{print $1}')"
|
||||
if [[ "${actual_sha512}" != "${expected_sha512}" ]]; then
|
||||
echo >&2 "sha512 mismatch for gvisor.tar.bz2: expected ${expected_sha512}, got ${actual_sha512}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Extract into a temporary directory, then install.
|
||||
tar -C "${tmpdir}" -xjf "${tarball}"
|
||||
|
||||
$SUDO install -m 0755 "${tmpdir}/runsc" /usr/local/bin/runsc
|
||||
$SUDO install -m 0755 "${tmpdir}/containerd-shim-runsc-v1" /usr/local/bin/containerd-shim-runsc-v1
|
||||
|
||||
# Install the gvisor-bin/ sidecar executables that runsc requires at runtime.
|
||||
# runsc looks for gvisor-bin/ next to its own executable.
|
||||
$SUDO mkdir -p /usr/local/bin/gvisor-bin
|
||||
$SUDO install -m 0755 "${tmpdir}"/gvisor-bin/* /usr/local/bin/gvisor-bin/
|
||||
Executable
+139
@@ -0,0 +1,139 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright The containerd Authors.
|
||||
|
||||
# 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.
|
||||
|
||||
#
|
||||
# Runs the integration-runsc CI test suite locally against an environment
|
||||
# provisioned by setup-runsc-test-env.sh.
|
||||
#
|
||||
# Usage: sudo CGROUP_DRIVER=systemd script/runsc/run-runsc-tests.sh
|
||||
#
|
||||
# Optional: set FOCUS to run a subset of cri-integration tests, e.g.
|
||||
# sudo FOCUS=TestContainerPrivileged ... run-runsc-tests.sh
|
||||
#
|
||||
set -eux -o pipefail
|
||||
|
||||
if [[ "$(id -u)" != "0" ]]; then
|
||||
echo "must be run as root (use sudo)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
: "${CGROUP_DRIVER:=systemd}"
|
||||
: "${FOCUS:=}"
|
||||
|
||||
script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" > /dev/null 2>&1; pwd -P)"
|
||||
containerd_dir="$(cd -- "${script_dir}/../.." > /dev/null 2>&1; pwd -P)"
|
||||
|
||||
export GOPATH="${GOPATH:-/go}"
|
||||
export PATH="/usr/local/go/bin:${GOPATH}/bin:/usr/local/bin:/usr/local/sbin:${PATH}"
|
||||
|
||||
report_dir="${containerd_dir}/report-runsc-${CGROUP_DRIVER}"
|
||||
mkdir -p "${report_dir}"
|
||||
|
||||
cd "${containerd_dir}"
|
||||
|
||||
# keep in sync with write-runsc-shim-config.sh
|
||||
_runsc_root=/run/containerd-runsc-test
|
||||
# write-runsc-shim-config.sh removes /run/containerd/runsc/config.toml (the
|
||||
# higher-precedence shim config path) before writing the test config to /etc.
|
||||
# Save both config paths now so the EXIT trap can restore them.
|
||||
_runsc_runtime_cfg=/run/containerd/runsc/config.toml
|
||||
_runsc_runtime_cfg_saved=
|
||||
if [[ -f "${_runsc_runtime_cfg}" ]]; then
|
||||
_runsc_runtime_cfg_saved="$(mktemp /tmp/containerd-runsc-runtime-cfg-XXXXXX.toml)"
|
||||
cp "${_runsc_runtime_cfg}" "${_runsc_runtime_cfg_saved}"
|
||||
fi
|
||||
|
||||
_runsc_etc_cfg=/etc/containerd/runsc/config.toml
|
||||
_runsc_etc_cfg_saved=
|
||||
if [[ -f "${_runsc_etc_cfg}" ]]; then
|
||||
_runsc_etc_cfg_saved="$(mktemp /tmp/containerd-runsc-etc-cfg-XXXXXX.toml)"
|
||||
cp "${_runsc_etc_cfg}" "${_runsc_etc_cfg_saved}"
|
||||
fi
|
||||
|
||||
# _cleanup_runsc_root kills any surviving shims and runsc workers that hold
|
||||
# mounts under _runsc_root busy, then removes the directory. Safe to call
|
||||
# multiple times; all operations are best-effort (|| true).
|
||||
_cleanup_runsc_root() {
|
||||
if command -v runsc >/dev/null 2>&1; then
|
||||
local _ids
|
||||
_ids="$(runsc --root="${_runsc_root}" list --quiet 2>/dev/null || true)"
|
||||
local _id
|
||||
for _id in ${_ids}; do
|
||||
runsc --root="${_runsc_root}" delete --force "${_id}" 2>/dev/null || true
|
||||
done
|
||||
fi
|
||||
# Kill shims before removing the root; they can hold state mounts busy.
|
||||
while IFS= read -r _pid; do
|
||||
[[ -z "${_pid}" ]] && continue
|
||||
kill -KILL "${_pid}" 2>/dev/null || true
|
||||
done < <(
|
||||
pgrep -f "containerd-shim-runsc-v1.*containerd-test" || true
|
||||
pgrep -f "runsc.*--root=${_runsc_root}" || true
|
||||
)
|
||||
# null-netns is a network-namespace bind-mount that findmnt may not
|
||||
# enumerate; unmount and kill holders explicitly before the retry loop.
|
||||
umount -l "${_runsc_root}/null-netns" 2>/dev/null || true
|
||||
fuser -km "${_runsc_root}/null-netns" 2>/dev/null || true
|
||||
local _i
|
||||
for _i in {1..20}; do
|
||||
if command -v findmnt >/dev/null 2>&1; then
|
||||
findmnt -R -n -o TARGET "${_runsc_root}" 2>/dev/null | sort -r |
|
||||
while IFS= read -r _mount; do
|
||||
[[ -z "${_mount}" ]] && continue
|
||||
umount -l "${_mount}" 2>/dev/null || true
|
||||
done
|
||||
fi
|
||||
rm -rf "${_runsc_root:?}" && return
|
||||
sleep 1
|
||||
done
|
||||
}
|
||||
|
||||
cfg=$(mktemp /tmp/containerd-config-runsc-XXXXXX.toml)
|
||||
# On exit: restore the pre-existing shim configs (if any were saved),
|
||||
# remove configs written by write-runsc-shim-config.sh when none existed,
|
||||
# clean up the runsc root, and remove the temp containerd config.
|
||||
trap '
|
||||
if [[ -n "${_runsc_runtime_cfg_saved}" ]]; then
|
||||
mv "${_runsc_runtime_cfg_saved}" "${_runsc_runtime_cfg}" 2>/dev/null || true
|
||||
fi
|
||||
if [[ -n "${_runsc_etc_cfg_saved}" ]]; then
|
||||
mv "${_runsc_etc_cfg_saved}" "${_runsc_etc_cfg}" 2>/dev/null || true
|
||||
else
|
||||
rm -f "${_runsc_etc_cfg}" 2>/dev/null || true
|
||||
fi
|
||||
_cleanup_runsc_root
|
||||
rm -f "${cfg}"
|
||||
' EXIT
|
||||
|
||||
"${script_dir}/write-runsc-shim-config.sh" "${CGROUP_DRIVER}" systrap
|
||||
"${script_dir}/write-containerd-runsc-config.sh" "${cfg}" "${CGROUP_DRIVER}"
|
||||
|
||||
# The generated config and runsc shim config already contain the cgroup settings.
|
||||
# Keep CGROUP_DRIVER set but empty so utils.sh does not append runc.options again.
|
||||
CGROUP_DRIVER= \
|
||||
FOCUS="${FOCUS}" \
|
||||
CONTAINERD_CONFIG_FILE="${cfg}" \
|
||||
RUNTIME=runsc \
|
||||
RUNTIME_TYPE=io.containerd.runsc.v1 \
|
||||
make cri-integration
|
||||
|
||||
echo "==> critest (CGROUP_DRIVER=${CGROUP_DRIVER})"
|
||||
CGROUP_DRIVER="${CGROUP_DRIVER}" \
|
||||
CONTAINERD_CONFIG_FILE="${cfg}" \
|
||||
"${script_dir}/critest-runsc.sh" "${report_dir}"
|
||||
|
||||
echo ""
|
||||
echo "All tests passed. Reports in: ${report_dir}"
|
||||
@@ -0,0 +1 @@
|
||||
20260817.0
|
||||
Executable
+80
@@ -0,0 +1,80 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright The containerd Authors.
|
||||
|
||||
# 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.
|
||||
|
||||
#
|
||||
# Provisions the local machine to run the integration-runsc CI job locally.
|
||||
# After running this setup script, use run-runsc-tests.sh to execute the test suite.
|
||||
#
|
||||
# Usage: sudo CGROUP_DRIVER=systemd script/runsc/setup-runsc-test-env.sh
|
||||
#
|
||||
set -eux -o pipefail
|
||||
|
||||
if [[ "$(id -u)" != "0" ]]; then
|
||||
echo "must be run as root (use sudo)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
: "${CGROUP_DRIVER:=systemd}"
|
||||
|
||||
script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" > /dev/null 2>&1; pwd -P)"
|
||||
setup_dir="$(cd -- "${script_dir}/../setup" > /dev/null 2>&1; pwd -P)"
|
||||
containerd_dir="$(cd -- "${script_dir}/../.." > /dev/null 2>&1; pwd -P)"
|
||||
|
||||
export GOPATH="${GOPATH:-/go}"
|
||||
export PATH="/usr/local/go/bin:${GOPATH}/bin:/usr/local/bin:/usr/local/sbin:${PATH}"
|
||||
|
||||
cd "${containerd_dir}"
|
||||
|
||||
echo "==> apt packages"
|
||||
apt-get update -q
|
||||
apt-get install -y gperf dmsetup strace xfsprogs
|
||||
|
||||
echo "==> libseccomp"
|
||||
"${setup_dir}/install-seccomp"
|
||||
|
||||
echo "==> runc"
|
||||
RUNC_FLAVOR=runc "${setup_dir}/install-runc"
|
||||
runc --version
|
||||
|
||||
echo "==> CNI plugins"
|
||||
"${setup_dir}/install-cni" "$(grep containernetworking/plugins go.mod | awk '{print $2}')"
|
||||
|
||||
echo "==> critools (critest + crictl)"
|
||||
"${setup_dir}/install-critools"
|
||||
critest --version
|
||||
crictl --version
|
||||
|
||||
echo "==> runsc (gVisor)"
|
||||
"${script_dir}/install-runsc"
|
||||
runsc --version
|
||||
containerd-shim-runsc-v1 -v
|
||||
|
||||
echo "==> build containerd + failpoint binaries"
|
||||
make BUILDTAGS="seccomp no_btrfs no_devmapper no_zfs" binaries
|
||||
make install
|
||||
# failpoint shim + CNI plugin + loopback-v2 needed by several cri-integration tests
|
||||
"${setup_dir}/install-failpoint-binaries"
|
||||
|
||||
echo "==> erofs (kernel module + userspace tools)"
|
||||
modprobe erofs || true
|
||||
apt-get install -y erofs-utils || true # best-effort; tests skip gracefully if unavailable
|
||||
|
||||
echo "==> configure containerd for runsc (CGROUP_DRIVER=${CGROUP_DRIVER})"
|
||||
CGROUP_DRIVER="${CGROUP_DRIVER}" "${script_dir}/config-containerd-runsc"
|
||||
|
||||
echo ""
|
||||
echo "Setup complete. Run tests with:"
|
||||
echo " sudo CGROUP_DRIVER=${CGROUP_DRIVER} script/runsc/run-runsc-tests.sh"
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright The containerd Authors.
|
||||
|
||||
# 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.
|
||||
|
||||
#
|
||||
# Writes a containerd config.toml for use with runsc (gVisor) into the path
|
||||
# given as the first argument. The second argument controls the cgroup driver:
|
||||
# pass "systemd" to enable the systemd driver, anything else selects cgroupfs.
|
||||
#
|
||||
# Usage: write-containerd-runsc-config.sh <output_path> <cgroup_driver>
|
||||
#
|
||||
# The runsc shim config (including platform and systemd-cgroup) must already
|
||||
# exist at /etc/containerd/runsc/config.toml before containerd is started.
|
||||
# Use write-runsc-shim-config.sh to write it.
|
||||
set -eu -o pipefail
|
||||
|
||||
output=${1:?output path argument is required}
|
||||
cgroup_driver=${2:?cgroup_driver argument is required: pass "systemd" or "cgroupfs"}
|
||||
# Normalize to a bare TOML boolean: accept "true"/"systemd" → true, anything else → false.
|
||||
case "${cgroup_driver}" in
|
||||
true|systemd) systemd_cgroup=true ;;
|
||||
*) systemd_cgroup=false ;;
|
||||
esac
|
||||
|
||||
cat > "${output}" <<EOF
|
||||
version = 2
|
||||
|
||||
[plugins."io.containerd.snapshotter.v1.overlayfs"]
|
||||
slow_chown = true
|
||||
|
||||
[plugins."io.containerd.grpc.v1.cri"]
|
||||
enable_selinux = false
|
||||
|
||||
[plugins."io.containerd.nri.v1.nri"]
|
||||
disable = false
|
||||
socket_path = "/var/run/nri-test.sock"
|
||||
plugin_path = "/no/pre-launched/nri/plugins"
|
||||
|
||||
[plugins."io.containerd.grpc.v1.cri".containerd]
|
||||
default_runtime_name = "runsc"
|
||||
|
||||
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
|
||||
runtime_type = "io.containerd.runc.v2"
|
||||
|
||||
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
|
||||
SystemdCgroup = ${systemd_cgroup}
|
||||
|
||||
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runsc]
|
||||
runtime_type = "io.containerd.runsc.v1"
|
||||
|
||||
# Point the runsc shim at its own config file so that all runsc-specific
|
||||
# settings (platform, systemd-cgroup, etc.) are read from one place.
|
||||
# This prevents containerd from overriding the shim config via ConfigBody.
|
||||
# Note: go-toml maps "ConfigPath" (not "config_path") to runtimeoptions.Options.ConfigPath.
|
||||
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runsc.options]
|
||||
ConfigPath = "/etc/containerd/runsc/config.toml"
|
||||
EOF
|
||||
Executable
+64
@@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Copyright The containerd Authors.
|
||||
|
||||
# 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.
|
||||
|
||||
#
|
||||
# Writes /etc/containerd/runsc/config.toml for containerd-shim-runsc-v1.
|
||||
# The shim reads its own config from this path rather than from the main
|
||||
# containerd config.toml.
|
||||
#
|
||||
# Usage: write-runsc-shim-config.sh <cgroup_driver> [<platform>]
|
||||
#
|
||||
# <cgroup_driver> pass "systemd" to enable the systemd cgroup driver;
|
||||
# anything else selects cgroupfs.
|
||||
# <platform> optional runsc platform (e.g. "systrap", "kvm").
|
||||
# Omit to let runsc use its compiled-in default.
|
||||
# Use "systrap" on hosts without KVM support (CI runners).
|
||||
#
|
||||
# The shim config sets root to a test-specific path (/run/containerd-runsc-test)
|
||||
# so sandbox state is isolated from the shared default (/run/containerd/runsc).
|
||||
# Callers that clean up after the test should remove /run/containerd-runsc-test.
|
||||
#
|
||||
set -eu -o pipefail
|
||||
|
||||
# Keep in sync with run-runsc-tests.sh and critest-runsc.sh.
|
||||
_runsc_test_root=/run/containerd-runsc-test
|
||||
|
||||
SUDO=''
|
||||
if [[ "$(id -u)" != "0" ]]; then
|
||||
SUDO='sudo'
|
||||
fi
|
||||
|
||||
case "${1:-false}" in
|
||||
true|systemd) systemd_cgroup='"true"' ;;
|
||||
*) systemd_cgroup='"false"' ;;
|
||||
esac
|
||||
|
||||
platform="${2:-}"
|
||||
|
||||
# Remove the higher-precedence runtime path to avoid stale overrides.
|
||||
${SUDO} rm -f /run/containerd/runsc/config.toml
|
||||
|
||||
${SUDO} mkdir -p /etc/containerd/runsc
|
||||
|
||||
{
|
||||
echo ""
|
||||
echo "[runsc_config]"
|
||||
echo " systemd-cgroup = ${systemd_cgroup}"
|
||||
echo " root = \"${_runsc_test_root}\""
|
||||
if [[ -n "${platform}" ]]; then
|
||||
echo " platform = \"${platform}\""
|
||||
fi
|
||||
} | ${SUDO} tee /etc/containerd/runsc/config.toml > /dev/null
|
||||
@@ -21,6 +21,12 @@
|
||||
#
|
||||
set -euo pipefail
|
||||
|
||||
# Some environments (e2e, Cirrus) run this script as root without sudo available.
|
||||
SUDO=''
|
||||
if [[ "$(id -u)" != "0" ]]; then
|
||||
SUDO='sudo'
|
||||
fi
|
||||
|
||||
base_dir="$(dirname "${BASH_SOURCE[0]}")"
|
||||
root_dir="$( cd "${base_dir}" && pwd )"/../..
|
||||
|
||||
@@ -28,16 +34,16 @@ cd "${root_dir}"
|
||||
|
||||
CNI_BIN_DIR=${CNI_BIN_DIR:-"/opt/cni/bin"}
|
||||
make bin/cni-bridge-fp
|
||||
sudo install bin/cni-bridge-fp "${CNI_BIN_DIR}"
|
||||
${SUDO} install bin/cni-bridge-fp "${CNI_BIN_DIR}"
|
||||
|
||||
SHIM_BIN_DIR=${SHIM_BIN_DIR:-"/usr/local/bin"}
|
||||
make bin/containerd-shim-runc-fp-v1
|
||||
sudo install bin/containerd-shim-runc-fp-v1 "${SHIM_BIN_DIR}"
|
||||
${SUDO} install bin/containerd-shim-runc-fp-v1 "${SHIM_BIN_DIR}"
|
||||
|
||||
RUNCFP_BIN_DIR=${RUNCFP_BIN_DIR:-"/usr/local/bin"}
|
||||
make bin/runc-fp
|
||||
sudo install bin/runc-fp "${RUNCFP_BIN_DIR}"
|
||||
${SUDO} install bin/runc-fp "${RUNCFP_BIN_DIR}"
|
||||
|
||||
LOOPBACKV2_BIN_DIR=${LOOPBACKV2_BIN_DIR:-"/usr/local/bin"}
|
||||
make bin/loopback-v2
|
||||
sudo install bin/loopback-v2 "${LOOPBACKV2_BIN_DIR}"
|
||||
${SUDO} install bin/loopback-v2 "${LOOPBACKV2_BIN_DIR}"
|
||||
@@ -37,6 +37,9 @@ else
|
||||
fi
|
||||
# RUNTIME is the runtime handler to use in the test.
|
||||
RUNTIME=${RUNTIME:-""}
|
||||
# RUNTIME_TYPE is the OCI runtime type for the default handler (e.g. io.containerd.runsc.v1).
|
||||
# Passed to --runtime-type so that runtimeHandlerIsRunsc() detects runsc regardless of handler name.
|
||||
RUNTIME_TYPE=${RUNTIME_TYPE:-""}
|
||||
|
||||
mkdir -p "${REPORT_DIR}"
|
||||
test_setup "${REPORT_DIR}"
|
||||
@@ -55,6 +58,7 @@ CMD+="${PWD}/bin/cri-integration.test${EXE_SUFFIX}"
|
||||
${CMD} --test.run="${FOCUS}" --test.v \
|
||||
--cri-endpoint="${CONTAINERD_SOCK}" \
|
||||
--runtime-handler="${RUNTIME}" \
|
||||
--runtime-type="${RUNTIME_TYPE}" \
|
||||
--containerd-bin="${CONTAINERD_BIN}" \
|
||||
--build-dir="${ROOT}/bin" \
|
||||
--image-list="${TEST_IMAGE_LIST:-}" "@" && test_exit_code=$? || test_exit_code=$?
|
||||
|
||||
@@ -64,7 +64,8 @@ skip_test_args=$(
|
||||
IFS='|'
|
||||
echo "${skip_tests[*]}"
|
||||
)
|
||||
critest_args=(--parallel=$(($(nproc) + 2)) --ginkgo.skip="${skip_test_args}")
|
||||
ginkgo_procs="${GINKGO_NODES:-$(($(nproc) + 2))}"
|
||||
critest_args=(--parallel="${ginkgo_procs}" --ginkgo.skip="${skip_test_args}")
|
||||
if [[ -n $REPORT_DIR ]]; then
|
||||
mkdir -p "${REPORT_DIR}"
|
||||
critest_args+=(--report-dir="${REPORT_DIR}")
|
||||
|
||||
Reference in new issue
Block a user