diff options
author | Adin Scannell <ascannell@google.com> | 2019-09-03 22:01:34 -0700 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2019-09-03 22:02:43 -0700 |
commit | 67a2ab1438cdccbe045143bbfaa807cf83110ebc (patch) | |
tree | 8c17f5ecd3e5b3e9c4decb46d8f2b2e893809dc1 | |
parent | 144127e5e1c548150f49501a7decb82ec2e239f2 (diff) |
Impose order on test scripts.
The simple test script has gotten out of control. Shard this script into
different pieces and attempt to impose order on overall test structure. This
change helps lay some of the foundations for future improvements.
* The runsc/test directories are moved into just test/.
* The runsc/test/testutil package is split into logical pieces.
* The scripts/ directory contains new top-level targets.
* Each test is now responsible for building targets it requires.
* The install functionality is moved into `runsc` itself for simplicity.
* The existing kokoro run_tests.sh file now just calls all (can be split).
After this change is merged, I will create multiple distinct workflows for
Kokoro, one for each of the scripts currently targeted by `run_tests.sh` today,
which should dramatically reduce the time-to-run for the Kokoro tests, and
provides a better foundation for further improvements to the infrastructure.
PiperOrigin-RevId: 267081397
-rw-r--r-- | kokoro/build.cfg | 23 | ||||
-rw-r--r-- | kokoro/common.cfg | 2 | ||||
-rw-r--r-- | kokoro/continuous.cfg | 8 | ||||
-rw-r--r-- | kokoro/do_tests.cfg | 9 | ||||
-rw-r--r-- | kokoro/docker_tests.cfg | 9 | ||||
-rw-r--r-- | kokoro/go.cfg | 6 | ||||
-rw-r--r-- | kokoro/go_test.cfg | 1 | ||||
-rw-r--r-- | kokoro/hostnet_tests.cfg | 9 | ||||
-rw-r--r-- | kokoro/kvm_tests.cfg | 9 | ||||
-rw-r--r-- | kokoro/make_tests.cfg | 9 | ||||
-rw-r--r-- | kokoro/overlay_tests.cfg | 9 | ||||
-rw-r--r-- | kokoro/presubmit.cfg | 6 | ||||
-rw-r--r-- | kokoro/release-nightly.cfg | 5 | ||||
-rw-r--r-- | kokoro/release.cfg | 1 | ||||
-rw-r--r-- | kokoro/root_tests.cfg | 9 | ||||
-rwxr-xr-x[l---------] | kokoro/run_build.sh | 20 | ||||
-rw-r--r--[l---------] | kokoro/run_tests.sh | 30 | ||||
-rw-r--r-- | kokoro/simple_tests.cfg | 9 | ||||
-rw-r--r-- | kokoro/syscall_tests.cfg | 9 | ||||
-rw-r--r-- | pkg/sentry/fsimpl/ext/BUILD | 2 | ||||
-rw-r--r-- | pkg/sentry/fsimpl/ext/ext_test.go | 2 | ||||
-rw-r--r-- | pkg/sentry/platform/kvm/BUILD | 1 | ||||
-rw-r--r-- | runsc/BUILD | 9 | ||||
-rw-r--r-- | runsc/cgroup/BUILD | 4 | ||||
-rw-r--r-- | runsc/cmd/BUILD | 3 | ||||
-rw-r--r-- | runsc/cmd/capability_test.go | 4 | ||||
-rw-r--r-- | runsc/cmd/install.go | 210 | ||||
-rw-r--r-- | runsc/container/BUILD | 2 | ||||
-rw-r--r-- | runsc/container/console_test.go | 2 | ||||
-rw-r--r-- | runsc/container/container_test.go | 33 | ||||
-rw-r--r-- | runsc/container/multi_container_test.go | 2 | ||||
-rw-r--r-- | runsc/container/shared_volume_test.go | 2 | ||||
-rw-r--r-- | runsc/container/test_app/BUILD | 2 | ||||
-rw-r--r-- | runsc/container/test_app/fds.go | 4 | ||||
-rw-r--r-- | runsc/container/test_app/test_app.go | 2 | ||||
-rw-r--r-- | runsc/criutil/BUILD | 12 | ||||
-rw-r--r-- | runsc/criutil/criutil.go (renamed from runsc/test/testutil/crictl.go) | 13 | ||||
-rwxr-xr-x | runsc/debian/postinst.sh | 6 | ||||
-rw-r--r-- | runsc/dockerutil/BUILD | 15 | ||||
-rw-r--r-- | runsc/dockerutil/dockerutil.go (renamed from runsc/test/testutil/docker.go) | 77 | ||||
-rw-r--r-- | runsc/main.go | 5 | ||||
-rw-r--r-- | runsc/test/BUILD | 0 | ||||
-rw-r--r-- | runsc/test/README.md | 24 | ||||
-rwxr-xr-x | runsc/test/install.sh | 93 | ||||
-rw-r--r-- | runsc/test/testutil/testutil_race.go | 21 | ||||
-rw-r--r-- | runsc/testutil/BUILD (renamed from runsc/test/testutil/BUILD) | 11 | ||||
-rw-r--r-- | runsc/testutil/testutil.go (renamed from runsc/test/testutil/testutil.go) | 37 | ||||
-rw-r--r-- | runsc/tools/dockercfg/BUILD | 10 | ||||
-rw-r--r-- | runsc/tools/dockercfg/dockercfg.go | 193 | ||||
-rwxr-xr-x | scripts/build.sh | 62 | ||||
-rwxr-xr-x | scripts/common.sh | 23 | ||||
-rwxr-xr-x | scripts/common_bazel.sh | 77 | ||||
-rwxr-xr-x | scripts/do_tests.sh | 27 | ||||
-rwxr-xr-x | scripts/docker_tests.sh | 22 | ||||
-rwxr-xr-x | scripts/go.sh | 34 | ||||
-rwxr-xr-x | scripts/hostnet_tests.sh | 22 | ||||
-rwxr-xr-x | scripts/kvm_tests.sh | 30 | ||||
-rwxr-xr-x | scripts/make_tests.sh | 24 | ||||
-rwxr-xr-x | scripts/overlay_tests.sh | 22 | ||||
-rwxr-xr-x | scripts/release.sh | 34 | ||||
-rwxr-xr-x | scripts/root_tests.sh | 31 | ||||
-rwxr-xr-x | scripts/simple_tests.sh | 20 | ||||
-rwxr-xr-x | scripts/syscall_tests.sh | 20 | ||||
-rw-r--r-- | test/README.md | 18 | ||||
-rw-r--r-- | test/e2e/BUILD (renamed from runsc/test/integration/BUILD) | 11 | ||||
-rw-r--r-- | test/e2e/exec_test.go (renamed from runsc/test/integration/exec_test.go) | 29 | ||||
-rw-r--r-- | test/e2e/integration.go (renamed from runsc/test/integration/integration.go) | 0 | ||||
-rw-r--r-- | test/e2e/integration_test.go (renamed from runsc/test/integration/integration_test.go) | 46 | ||||
-rw-r--r-- | test/e2e/regression_test.go (renamed from runsc/test/integration/regression_test.go) | 6 | ||||
-rw-r--r-- | test/image/BUILD (renamed from runsc/test/image/BUILD) | 13 | ||||
-rw-r--r-- | test/image/image.go (renamed from runsc/test/image/image.go) | 0 | ||||
-rw-r--r-- | test/image/image_test.go (renamed from runsc/test/image/image_test.go) | 65 | ||||
-rw-r--r-- | test/image/latin10k.txt (renamed from runsc/test/image/latin10k.txt) | 0 | ||||
-rw-r--r-- | test/image/mysql.sql (renamed from runsc/test/image/mysql.sql) | 0 | ||||
-rw-r--r-- | test/image/ruby.rb (renamed from runsc/test/image/ruby.rb) | 0 | ||||
-rw-r--r-- | test/image/ruby.sh (renamed from runsc/test/image/ruby.sh) | 0 | ||||
-rw-r--r-- | test/root/BUILD (renamed from runsc/test/root/BUILD) | 9 | ||||
-rw-r--r-- | test/root/cgroup_test.go (renamed from runsc/test/root/cgroup_test.go) | 11 | ||||
-rw-r--r-- | test/root/chroot_test.go (renamed from runsc/test/root/chroot_test.go) | 17 | ||||
-rw-r--r-- | test/root/crictl_test.go (renamed from runsc/test/root/crictl_test.go) | 44 | ||||
-rw-r--r-- | test/root/root.go (renamed from runsc/test/root/root.go) | 0 | ||||
-rw-r--r-- | test/root/testdata/BUILD (renamed from runsc/test/root/testdata/BUILD) | 2 | ||||
-rw-r--r-- | test/root/testdata/busybox.go (renamed from runsc/test/root/testdata/busybox.go) | 0 | ||||
-rw-r--r-- | test/root/testdata/containerd_config.go (renamed from runsc/test/root/testdata/containerd_config.go) | 0 | ||||
-rw-r--r-- | test/root/testdata/httpd.go (renamed from runsc/test/root/testdata/httpd.go) | 0 | ||||
-rw-r--r-- | test/root/testdata/httpd_mount_paths.go (renamed from runsc/test/root/testdata/httpd_mount_paths.go) | 0 | ||||
-rw-r--r-- | test/root/testdata/sandbox.go (renamed from runsc/test/root/testdata/sandbox.go) | 0 | ||||
-rw-r--r-- | test/runtimes/BUILD | 4 | ||||
-rw-r--r-- | test/runtimes/build_defs.bzl (renamed from runsc/test/build_defs.bzl) | 0 | ||||
-rw-r--r-- | test/runtimes/common/BUILD | 2 | ||||
-rw-r--r-- | test/runtimes/common/common_test.go | 2 | ||||
-rw-r--r-- | test/runtimes/runtimes_test.go | 2 | ||||
-rw-r--r-- | test/syscalls/BUILD | 3 | ||||
-rw-r--r-- | test/syscalls/build_defs.bzl | 1 | ||||
-rw-r--r-- | test/syscalls/syscall_test_runner.go | 2 | ||||
-rwxr-xr-x | tools/make_repository.sh | 69 | ||||
-rwxr-xr-x | tools/run_build.sh | 49 | ||||
-rwxr-xr-x | tools/run_tests.sh | 304 |
98 files changed, 1215 insertions, 926 deletions
diff --git a/kokoro/build.cfg b/kokoro/build.cfg new file mode 100644 index 000000000..d67af4694 --- /dev/null +++ b/kokoro/build.cfg @@ -0,0 +1,23 @@ +build_file: "repo/scripts/build.sh" + +before_action { + fetch_keystore { + keystore_resource { + keystore_config_id: 73898 + keyname: "kokoro-repo-key" + } + } +} + +env_vars { + key: "KOKORO_REPO_KEY" + value: "$KOKORO_ROOT/src/keystore/73898_kokoro-repo-key" +} + +action { + define_artifacts { + regex: "**/runsc" + regex: "**/runsc.sha256" + regex: "**/repo/**" + } +} diff --git a/kokoro/common.cfg b/kokoro/common.cfg index cad873fe1..669a2e458 100644 --- a/kokoro/common.cfg +++ b/kokoro/common.cfg @@ -10,7 +10,7 @@ before_action { # Configure bazel to access RBE. bazel_setting { - # Our GCP project name + # Our GCP project name. project_id: "gvisor-rbe" # Use RBE for execution as well as caching. diff --git a/kokoro/continuous.cfg b/kokoro/continuous.cfg index 8da47736a..88694220a 100644 --- a/kokoro/continuous.cfg +++ b/kokoro/continuous.cfg @@ -1,13 +1,11 @@ -# Location of bash script that runs the test. The first directory in the path -# is the directory where Kokoro will check out the repo. The rest is the path -# is the path to the test script. -build_file: "repo/kokoro/run_tests.sh" +# This is a temporary file. It will be removed when new Kokoro jobs exist for +# all the other presubmits. +build_file: "repo/scripts/build.sh" action { define_artifacts { regex: "**/sponge_log.xml" regex: "**/sponge_log.log" regex: "**/outputs.zip" - regex: "**/runsc-logs.tar.gz" } } diff --git a/kokoro/do_tests.cfg b/kokoro/do_tests.cfg new file mode 100644 index 000000000..b45ec0b42 --- /dev/null +++ b/kokoro/do_tests.cfg @@ -0,0 +1,9 @@ +build_file: "repo/scripts/do_tests.sh" + +action { + define_artifacts { + regex: "**/sponge_log.xml" + regex: "**/sponge_log.log" + regex: "**/outputs.zip" + } +} diff --git a/kokoro/docker_tests.cfg b/kokoro/docker_tests.cfg new file mode 100644 index 000000000..717d71dd3 --- /dev/null +++ b/kokoro/docker_tests.cfg @@ -0,0 +1,9 @@ +build_file: "repo/scripts/docker_tests.sh" + +action { + define_artifacts { + regex: "**/sponge_log.xml" + regex: "**/sponge_log.log" + regex: "**/outputs.zip" + } +} diff --git a/kokoro/go.cfg b/kokoro/go.cfg new file mode 100644 index 000000000..d1577252a --- /dev/null +++ b/kokoro/go.cfg @@ -0,0 +1,6 @@ +build_file: "repo/scripts/go.sh" + +env_vars { + key: "KOKORO_GO_PUSH" + value: "true" +} diff --git a/kokoro/go_test.cfg b/kokoro/go_test.cfg new file mode 100644 index 000000000..5eb51041a --- /dev/null +++ b/kokoro/go_test.cfg @@ -0,0 +1 @@ +build_file: "repo/scripts/go.sh" diff --git a/kokoro/hostnet_tests.cfg b/kokoro/hostnet_tests.cfg new file mode 100644 index 000000000..532755f4a --- /dev/null +++ b/kokoro/hostnet_tests.cfg @@ -0,0 +1,9 @@ +build_file: "repo/scripts/hostnet_tests.sh" + +action { + define_artifacts { + regex: "**/sponge_log.xml" + regex: "**/sponge_log.log" + regex: "**/outputs.zip" + } +} diff --git a/kokoro/kvm_tests.cfg b/kokoro/kvm_tests.cfg new file mode 100644 index 000000000..54365c2b2 --- /dev/null +++ b/kokoro/kvm_tests.cfg @@ -0,0 +1,9 @@ +build_file: "repo/scripts/kvm_tests.sh" + +action { + define_artifacts { + regex: "**/sponge_log.xml" + regex: "**/sponge_log.log" + regex: "**/outputs.zip" + } +} diff --git a/kokoro/make_tests.cfg b/kokoro/make_tests.cfg new file mode 100644 index 000000000..d973130ff --- /dev/null +++ b/kokoro/make_tests.cfg @@ -0,0 +1,9 @@ +build_file: "repo/scripts/make_tests.sh" + +action { + define_artifacts { + regex: "**/sponge_log.xml" + regex: "**/sponge_log.log" + regex: "**/outputs.zip" + } +} diff --git a/kokoro/overlay_tests.cfg b/kokoro/overlay_tests.cfg new file mode 100644 index 000000000..abd96f60c --- /dev/null +++ b/kokoro/overlay_tests.cfg @@ -0,0 +1,9 @@ +build_file: "repo/scripts/overlay_tests.sh" + +action { + define_artifacts { + regex: "**/sponge_log.xml" + regex: "**/sponge_log.log" + regex: "**/outputs.zip" + } +} diff --git a/kokoro/presubmit.cfg b/kokoro/presubmit.cfg index 8da47736a..eb0c78ea4 100644 --- a/kokoro/presubmit.cfg +++ b/kokoro/presubmit.cfg @@ -1,6 +1,5 @@ -# Location of bash script that runs the test. The first directory in the path -# is the directory where Kokoro will check out the repo. The rest is the path -# is the path to the test script. +# This is a temporary file. It will be removed when new Kokoro jobs exist for +# all the other presubmits. build_file: "repo/kokoro/run_tests.sh" action { @@ -8,6 +7,5 @@ action { regex: "**/sponge_log.xml" regex: "**/sponge_log.log" regex: "**/outputs.zip" - regex: "**/runsc-logs.tar.gz" } } diff --git a/kokoro/release-nightly.cfg b/kokoro/release-nightly.cfg index e5087b1cd..ae134258c 100644 --- a/kokoro/release-nightly.cfg +++ b/kokoro/release-nightly.cfg @@ -1,9 +1,8 @@ -# Location of bash script that builds a release. +# This file is a temporary bridge. It will be removed shortly, when Kokoro jobs +# are configured to point at the new build and release configurations. build_file: "repo/kokoro/run_build.sh" action { - # Upload runsc binary and its checksum. It may be in multiple paths, so we - # must use the wildcard. define_artifacts { regex: "**/runsc" regex: "**/runsc.sha512" diff --git a/kokoro/release.cfg b/kokoro/release.cfg new file mode 100644 index 000000000..b9d35bc51 --- /dev/null +++ b/kokoro/release.cfg @@ -0,0 +1 @@ +build_file: "repo/scripts/release.sh" diff --git a/kokoro/root_tests.cfg b/kokoro/root_tests.cfg new file mode 100644 index 000000000..20b97766a --- /dev/null +++ b/kokoro/root_tests.cfg @@ -0,0 +1,9 @@ +build_file: "repo/scripts/root_tests.sh" + +action { + define_artifacts { + regex: "**/sponge_log.xml" + regex: "**/sponge_log.log" + regex: "**/outputs.zip" + } +} diff --git a/kokoro/run_build.sh b/kokoro/run_build.sh index 9deafe9bb..da6a0c85e 120000..100755 --- a/kokoro/run_build.sh +++ b/kokoro/run_build.sh @@ -1 +1,19 @@ -../tools/run_build.sh
\ No newline at end of file +#!/bin/bash + +# Copyright 2018 The gVisor 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. + +# This file is a temporary bridge. We will create multiple independent Kokoro +# workflows that call each of the build scripts independently. +KOKORO_BUILD_NIGHTLY=true $(dirname $0)/../scripts/build.sh diff --git a/kokoro/run_tests.sh b/kokoro/run_tests.sh index 931cd2622..5552da11c 120000..100644 --- a/kokoro/run_tests.sh +++ b/kokoro/run_tests.sh @@ -1 +1,29 @@ -../tools/run_tests.sh
\ No newline at end of file +#!/bin/bash + +# Copyright 2019 The gVisor 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. + +set -xeo pipefail + +# This file is a temporary bridge. We will create multiple independent Kokoro +# workflows that call each of the test scripts independently. + +# Run all the tests in sequence. +$(dirname $0)/../scripts/do_tests.sh +$(dirname $0)/../scripts/make_tests.sh +$(dirname $0)/../scripts/root_tests.sh +$(dirname $0)/../scripts/docker_tests.sh +$(dirname $0)/../scripts/overlay_tests.sh +$(dirname $0)/../scripts/hostnet_tests.sh +$(dirname $0)/../scripts/simple_tests.sh diff --git a/kokoro/simple_tests.cfg b/kokoro/simple_tests.cfg new file mode 100644 index 000000000..32e0a9431 --- /dev/null +++ b/kokoro/simple_tests.cfg @@ -0,0 +1,9 @@ +build_file: "repo/scripts/simple_tests.sh" + +action { + define_artifacts { + regex: "**/sponge_log.xml" + regex: "**/sponge_log.log" + regex: "**/outputs.zip" + } +} diff --git a/kokoro/syscall_tests.cfg b/kokoro/syscall_tests.cfg new file mode 100644 index 000000000..ee6e4a3a4 --- /dev/null +++ b/kokoro/syscall_tests.cfg @@ -0,0 +1,9 @@ +build_file: "repo/scripts/syscall_tests.sh" + +action { + define_artifacts { + regex: "**/sponge_log.xml" + regex: "**/sponge_log.log" + regex: "**/outputs.zip" + } +} diff --git a/pkg/sentry/fsimpl/ext/BUILD b/pkg/sentry/fsimpl/ext/BUILD index a41101339..9e8ebb907 100644 --- a/pkg/sentry/fsimpl/ext/BUILD +++ b/pkg/sentry/fsimpl/ext/BUILD @@ -79,7 +79,7 @@ go_test( "//pkg/sentry/usermem", "//pkg/sentry/vfs", "//pkg/syserror", - "//runsc/test/testutil", + "//runsc/testutil", "@com_github_google_go-cmp//cmp:go_default_library", "@com_github_google_go-cmp//cmp/cmpopts:go_default_library", ], diff --git a/pkg/sentry/fsimpl/ext/ext_test.go b/pkg/sentry/fsimpl/ext/ext_test.go index 49b57a2d6..63cf7aeaf 100644 --- a/pkg/sentry/fsimpl/ext/ext_test.go +++ b/pkg/sentry/fsimpl/ext/ext_test.go @@ -33,7 +33,7 @@ import ( "gvisor.dev/gvisor/pkg/sentry/vfs" "gvisor.dev/gvisor/pkg/syserror" - "gvisor.dev/gvisor/runsc/test/testutil" + "gvisor.dev/gvisor/runsc/testutil" ) const ( diff --git a/pkg/sentry/platform/kvm/BUILD b/pkg/sentry/platform/kvm/BUILD index ad8b95744..fe979dccf 100644 --- a/pkg/sentry/platform/kvm/BUILD +++ b/pkg/sentry/platform/kvm/BUILD @@ -54,6 +54,7 @@ go_test( ], embed = [":kvm"], tags = [ + "manual", "nogotsan", "requires-kvm", ], diff --git a/runsc/BUILD b/runsc/BUILD index cc8852d7d..a2a465e1e 100644 --- a/runsc/BUILD +++ b/runsc/BUILD @@ -67,19 +67,10 @@ pkg_tar( ) pkg_tar( - name = "runsc-tools", - srcs = ["//runsc/tools/dockercfg"], - mode = "0755", - package_dir = "/usr/libexec/runsc", - strip_prefix = "/runsc/tools/dockercfg/linux_amd64_stripped", -) - -pkg_tar( name = "debian-data", extension = "tar.gz", deps = [ ":runsc-bin", - ":runsc-tools", ], ) diff --git a/runsc/cgroup/BUILD b/runsc/cgroup/BUILD index ab2387614..d6165f9e5 100644 --- a/runsc/cgroup/BUILD +++ b/runsc/cgroup/BUILD @@ -6,9 +6,7 @@ go_library( name = "cgroup", srcs = ["cgroup.go"], importpath = "gvisor.dev/gvisor/runsc/cgroup", - visibility = [ - "//runsc:__subpackages__", - ], + visibility = ["//:sandbox"], deps = [ "//pkg/log", "//runsc/specutils", diff --git a/runsc/cmd/BUILD b/runsc/cmd/BUILD index 5223b9972..250845ad7 100644 --- a/runsc/cmd/BUILD +++ b/runsc/cmd/BUILD @@ -19,6 +19,7 @@ go_library( "exec.go", "gofer.go", "help.go", + "install.go", "kill.go", "list.go", "path.go", @@ -81,7 +82,7 @@ go_test( "//runsc/boot", "//runsc/container", "//runsc/specutils", - "//runsc/test/testutil", + "//runsc/testutil", "@com_github_google_go-cmp//cmp:go_default_library", "@com_github_google_go-cmp//cmp/cmpopts:go_default_library", "@com_github_opencontainers_runtime-spec//specs-go:go_default_library", diff --git a/runsc/cmd/capability_test.go b/runsc/cmd/capability_test.go index 3ae25a257..0c27f7313 100644 --- a/runsc/cmd/capability_test.go +++ b/runsc/cmd/capability_test.go @@ -15,6 +15,7 @@ package cmd import ( + "flag" "fmt" "os" "testing" @@ -25,7 +26,7 @@ import ( "gvisor.dev/gvisor/runsc/boot" "gvisor.dev/gvisor/runsc/container" "gvisor.dev/gvisor/runsc/specutils" - "gvisor.dev/gvisor/runsc/test/testutil" + "gvisor.dev/gvisor/runsc/testutil" ) func init() { @@ -121,6 +122,7 @@ func TestCapabilities(t *testing.T) { } func TestMain(m *testing.M) { + flag.Parse() specutils.MaybeRunAsRoot() os.Exit(m.Run()) } diff --git a/runsc/cmd/install.go b/runsc/cmd/install.go new file mode 100644 index 000000000..441c1db0d --- /dev/null +++ b/runsc/cmd/install.go @@ -0,0 +1,210 @@ +// Copyright 2019 The gVisor 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. + +package cmd + +import ( + "context" + "encoding/json" + "fmt" + "io/ioutil" + "log" + "os" + "path" + + "flag" + "github.com/google/subcommands" +) + +// Install implements subcommands.Command. +type Install struct { + ConfigFile string + Runtime string + Experimental bool +} + +// Name implements subcommands.Command.Name. +func (*Install) Name() string { + return "install" +} + +// Synopsis implements subcommands.Command.Synopsis. +func (*Install) Synopsis() string { + return "adds a runtime to docker daemon configuration" +} + +// Usage implements subcommands.Command.Usage. +func (*Install) Usage() string { + return `install [flags] <name> [-- [args...]] -- if provided, args are passed to the runtime +` +} + +// SetFlags implements subcommands.Command.SetFlags. +func (i *Install) SetFlags(fs *flag.FlagSet) { + fs.StringVar(&i.ConfigFile, "config_file", "/etc/docker/daemon.json", "path to Docker daemon config file") + fs.StringVar(&i.Runtime, "runtime", "runsc", "runtime name") + fs.BoolVar(&i.Experimental, "experimental", false, "enable experimental features") +} + +// Execute implements subcommands.Command.Execute. +func (i *Install) Execute(_ context.Context, f *flag.FlagSet, args ...interface{}) subcommands.ExitStatus { + // Grab the name and arguments. + runtimeArgs := f.Args() + + // Extract the executable. + path, err := os.Executable() + if err != nil { + log.Fatalf("Error reading current exectuable: %v", err) + } + + // Load the configuration file. + c, err := readConfig(i.ConfigFile) + if err != nil { + log.Fatalf("Error reading config file %q: %v", i.ConfigFile, err) + } + + // Add the given runtime. + var rts map[string]interface{} + if i, ok := c["runtimes"]; ok { + rts = i.(map[string]interface{}) + } else { + rts = make(map[string]interface{}) + c["runtimes"] = rts + } + rts[i.Runtime] = struct { + Path string `json:"path,omitempty"` + RuntimeArgs []string `json:"runtimeArgs,omitempty"` + }{ + Path: path, + RuntimeArgs: runtimeArgs, + } + + // Set experimental if required. + if i.Experimental { + c["experimental"] = true + } + + // Write out the runtime. + if err := writeConfig(c, i.ConfigFile); err != nil { + log.Fatalf("Error writing config file %q: %v", i.ConfigFile, err) + } + + // Success. + log.Printf("Added runtime %q with arguments %v to %q.", i.Runtime, runtimeArgs, i.ConfigFile) + return subcommands.ExitSuccess +} + +// Uninstall implements subcommands.Command. +type Uninstall struct { + ConfigFile string + Runtime string +} + +// Name implements subcommands.Command.Name. +func (*Uninstall) Name() string { + return "uninstall" +} + +// Synopsis implements subcommands.Command.Synopsis. +func (*Uninstall) Synopsis() string { + return "removes a runtime from docker daemon configuration" +} + +// Usage implements subcommands.Command.Usage. +func (*Uninstall) Usage() string { + return `uninstall [flags] <name> +` +} + +// SetFlags implements subcommands.Command.SetFlags. +func (u *Uninstall) SetFlags(fs *flag.FlagSet) { + fs.StringVar(&u.ConfigFile, "config_file", "/etc/docker/daemon.json", "path to Docker daemon config file") + fs.StringVar(&u.Runtime, "runtime", "runsc", "runtime name") +} + +// Execute implements subcommands.Command.Execute. +func (u *Uninstall) Execute(_ context.Context, f *flag.FlagSet, args ...interface{}) subcommands.ExitStatus { + log.Printf("Removing runtime %q from %q.", u.Runtime, u.ConfigFile) + + c, err := readConfig(u.ConfigFile) + if err != nil { + log.Fatalf("Error reading config file %q: %v", u.ConfigFile, err) + } + + var rts map[string]interface{} + if i, ok := c["runtimes"]; ok { + rts = i.(map[string]interface{}) + } else { + log.Fatalf("runtime %q not found", u.Runtime) + } + if _, ok := rts[u.Runtime]; !ok { + log.Fatalf("runtime %q not found", u.Runtime) + } + delete(rts, u.Runtime) + + if err := writeConfig(c, u.ConfigFile); err != nil { + log.Fatalf("Error writing config file %q: %v", u.ConfigFile, err) + } + return subcommands.ExitSuccess +} + +func readConfig(path string) (map[string]interface{}, error) { + // Read the configuration data. + configBytes, err := ioutil.ReadFile(path) + if err != nil && !os.IsNotExist(err) { + return nil, err + } + + // Unmarshal the configuration. + c := make(map[string]interface{}) + if len(configBytes) > 0 { + if err := json.Unmarshal(configBytes, &c); err != nil { + return nil, err + } + } + + return c, nil +} + +func writeConfig(c map[string]interface{}, filename string) error { + // Marshal the configuration. + b, err := json.MarshalIndent(c, "", " ") + if err != nil { + return err + } + + // Copy the old configuration. + old, err := ioutil.ReadFile(filename) + if err != nil { + if !os.IsNotExist(err) { + return fmt.Errorf("error reading config file %q: %v", filename, err) + } + } else { + if err := ioutil.WriteFile(filename+"~", old, 0644); err != nil { + return fmt.Errorf("error backing up config file %q: %v", filename, err) + } + } + + // Make the necessary directories. + if err := os.MkdirAll(path.Dir(filename), 0755); err != nil { + return fmt.Errorf("error creating config directory for %q: %v", filename, err) + } + + // Write the new configuration. + if err := ioutil.WriteFile(filename, b, 0644); err != nil { + return fmt.Errorf("error writing config file %q: %v", filename, err) + } + + return nil +} diff --git a/runsc/container/BUILD b/runsc/container/BUILD index de8202bb1..bc1fa25e3 100644 --- a/runsc/container/BUILD +++ b/runsc/container/BUILD @@ -56,7 +56,7 @@ go_test( "//runsc/boot", "//runsc/boot/platforms", "//runsc/specutils", - "//runsc/test/testutil", + "//runsc/testutil", "@com_github_cenkalti_backoff//:go_default_library", "@com_github_kr_pty//:go_default_library", "@com_github_opencontainers_runtime-spec//specs-go:go_default_library", diff --git a/runsc/container/console_test.go b/runsc/container/console_test.go index e9372989f..7d67c3a75 100644 --- a/runsc/container/console_test.go +++ b/runsc/container/console_test.go @@ -30,7 +30,7 @@ import ( "gvisor.dev/gvisor/pkg/sentry/control" "gvisor.dev/gvisor/pkg/unet" "gvisor.dev/gvisor/pkg/urpc" - "gvisor.dev/gvisor/runsc/test/testutil" + "gvisor.dev/gvisor/runsc/testutil" ) // socketPath creates a path inside bundleDir and ensures that the returned diff --git a/runsc/container/container_test.go b/runsc/container/container_test.go index 3d4f304f3..2ac12e5b6 100644 --- a/runsc/container/container_test.go +++ b/runsc/container/container_test.go @@ -16,6 +16,7 @@ package container import ( "bytes" + "flag" "fmt" "io" "io/ioutil" @@ -39,7 +40,7 @@ import ( "gvisor.dev/gvisor/runsc/boot" "gvisor.dev/gvisor/runsc/boot/platforms" "gvisor.dev/gvisor/runsc/specutils" - "gvisor.dev/gvisor/runsc/test/testutil" + "gvisor.dev/gvisor/runsc/testutil" ) // waitForProcessList waits for the given process list to show up in the container. @@ -155,12 +156,7 @@ func waitForFile(f *os.File) error { return nil } - timeout := 5 * time.Second - if testutil.RaceEnabled { - // Race makes slow things even slow, so bump the timeout. - timeout = 3 * timeout - } - return testutil.Poll(op, timeout) + return testutil.Poll(op, 30*time.Second) } // readOutputNum reads a file at given filepath and returns the int at the @@ -254,10 +250,6 @@ func configs(opts ...configOption) []*boot.Config { // TODO(b/112165693): KVM tests are flaky. Disable until fixed. continue - // TODO(b/68787993): KVM doesn't work with --race. - if testutil.RaceEnabled { - continue - } c.Platform = platforms.KVM case nonExclusiveFS: c.FileAccess = boot.FileAccessShared @@ -1651,22 +1643,27 @@ func TestGoferExits(t *testing.T) { } func TestRootNotMount(t *testing.T) { - if testutil.RaceEnabled { - // Requires statically linked binary, since it's mapping the root to a - // random dir, libs cannot be located. - t.Skip("race makes test_app not statically linked") - } - appSym, err := testutil.FindFile("runsc/container/test_app/test_app") if err != nil { t.Fatal("error finding test_app:", err) } + app, err := filepath.EvalSymlinks(appSym) if err != nil { t.Fatalf("error resolving %q symlink: %v", appSym, err) } log.Infof("App path %q is a symlink to %q", appSym, app) + static, err := testutil.IsStatic(app) + if err != nil { + t.Fatalf("error reading application binary: %v", err) + } + if !static { + // This happens during race builds; we cannot map in shared + // libraries also, so we need to skip the test. + t.Skip() + } + root := filepath.Dir(app) exe := "/" + filepath.Base(app) log.Infof("Executing %q in %q", exe, root) @@ -2067,10 +2064,10 @@ func (cont *Container) executeSync(args *control.ExecArgs) (syscall.WaitStatus, func TestMain(m *testing.M) { log.SetLevel(log.Debug) + flag.Parse() if err := testutil.ConfigureExePath(); err != nil { panic(err.Error()) } specutils.MaybeRunAsRoot() - os.Exit(m.Run()) } diff --git a/runsc/container/multi_container_test.go b/runsc/container/multi_container_test.go index ae03d24b4..6e5f23ff2 100644 --- a/runsc/container/multi_container_test.go +++ b/runsc/container/multi_container_test.go @@ -32,7 +32,7 @@ import ( "gvisor.dev/gvisor/pkg/sentry/kernel" "gvisor.dev/gvisor/runsc/boot" "gvisor.dev/gvisor/runsc/specutils" - "gvisor.dev/gvisor/runsc/test/testutil" + "gvisor.dev/gvisor/runsc/testutil" ) func createSpecs(cmds ...[]string) ([]*specs.Spec, []string) { diff --git a/runsc/container/shared_volume_test.go b/runsc/container/shared_volume_test.go index 1f90d2462..dc4194134 100644 --- a/runsc/container/shared_volume_test.go +++ b/runsc/container/shared_volume_test.go @@ -25,7 +25,7 @@ import ( "gvisor.dev/gvisor/pkg/sentry/control" "gvisor.dev/gvisor/pkg/sentry/kernel/auth" "gvisor.dev/gvisor/runsc/boot" - "gvisor.dev/gvisor/runsc/test/testutil" + "gvisor.dev/gvisor/runsc/testutil" ) // TestSharedVolume checks that modifications to a volume mount are propagated diff --git a/runsc/container/test_app/BUILD b/runsc/container/test_app/BUILD index 82dbd54d2..9bf9e6e9d 100644 --- a/runsc/container/test_app/BUILD +++ b/runsc/container/test_app/BUILD @@ -13,7 +13,7 @@ go_binary( visibility = ["//runsc/container:__pkg__"], deps = [ "//pkg/unet", - "//runsc/test/testutil", + "//runsc/testutil", "@com_github_google_subcommands//:go_default_library", ], ) diff --git a/runsc/container/test_app/fds.go b/runsc/container/test_app/fds.go index c12809cab..a90cc1662 100644 --- a/runsc/container/test_app/fds.go +++ b/runsc/container/test_app/fds.go @@ -24,7 +24,7 @@ import ( "flag" "github.com/google/subcommands" "gvisor.dev/gvisor/pkg/unet" - "gvisor.dev/gvisor/runsc/test/testutil" + "gvisor.dev/gvisor/runsc/testutil" ) const fileContents = "foobarbaz" @@ -60,7 +60,7 @@ func (fds *fdSender) Execute(ctx context.Context, f *flag.FlagSet, args ...inter log.Fatalf("socket flag must be set") } - dir, err := ioutil.TempDir(testutil.TmpDir(), "") + dir, err := ioutil.TempDir("", "") if err != nil { log.Fatalf("TempDir failed: %v", err) } diff --git a/runsc/container/test_app/test_app.go b/runsc/container/test_app/test_app.go index 6578c7b41..7f735c254 100644 --- a/runsc/container/test_app/test_app.go +++ b/runsc/container/test_app/test_app.go @@ -29,7 +29,7 @@ import ( "flag" "github.com/google/subcommands" - "gvisor.dev/gvisor/runsc/test/testutil" + "gvisor.dev/gvisor/runsc/testutil" ) func main() { diff --git a/runsc/criutil/BUILD b/runsc/criutil/BUILD new file mode 100644 index 000000000..558133a0e --- /dev/null +++ b/runsc/criutil/BUILD @@ -0,0 +1,12 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +package(licenses = ["notice"]) + +go_library( + name = "criutil", + testonly = 1, + srcs = ["criutil.go"], + importpath = "gvisor.dev/gvisor/runsc/criutil", + visibility = ["//:sandbox"], + deps = ["//runsc/testutil"], +) diff --git a/runsc/test/testutil/crictl.go b/runsc/criutil/criutil.go index 4f9ee0c05..c8ddf5a9a 100644 --- a/runsc/test/testutil/crictl.go +++ b/runsc/criutil/criutil.go @@ -12,7 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -package testutil +// Package criutil contains utility functions for interacting with the +// Container Runtime Interface (CRI), principally via the crictl command line +// tool. This requires critools to be installed on the local system. +package criutil import ( "encoding/json" @@ -21,6 +24,8 @@ import ( "os/exec" "strings" "time" + + "gvisor.dev/gvisor/runsc/testutil" ) const endpointPrefix = "unix://" @@ -160,11 +165,11 @@ func (cc *Crictl) StartPodAndContainer(image, sbSpec, contSpec string) (string, } // Write the specs to files that can be read by crictl. - sbSpecFile, err := WriteTmpFile("sbSpec", sbSpec) + sbSpecFile, err := testutil.WriteTmpFile("sbSpec", sbSpec) if err != nil { return "", "", fmt.Errorf("failed to write sandbox spec: %v", err) } - contSpecFile, err := WriteTmpFile("contSpec", contSpec) + contSpecFile, err := testutil.WriteTmpFile("contSpec", contSpec) if err != nil { return "", "", fmt.Errorf("failed to write container spec: %v", err) } @@ -233,7 +238,7 @@ func (cc *Crictl) run(args ...string) (string, error) { case err := <-errCh: return "", err case <-time.After(cc.timeout): - if err := KillCommand(cmd); err != nil { + if err := testutil.KillCommand(cmd); err != nil { return "", fmt.Errorf("timed out, then couldn't kill process %+v: %v", cmd, err) } return "", fmt.Errorf("timed out: %+v", cmd) diff --git a/runsc/debian/postinst.sh b/runsc/debian/postinst.sh index 03a5ff524..dc7aeee87 100755 --- a/runsc/debian/postinst.sh +++ b/runsc/debian/postinst.sh @@ -15,10 +15,10 @@ # limitations under the License. if [ "$1" != configure ]; then - exit 0 + exit 0 fi if [ -f /etc/docker/daemon.json ]; then - /usr/libexec/runsc/dockercfg runtime-add runsc /usr/bin/runsc - systemctl restart docker + runsc install + systemctl restart docker || echo "unable to restart docker; you must do so manually." >&2 fi diff --git a/runsc/dockerutil/BUILD b/runsc/dockerutil/BUILD new file mode 100644 index 000000000..0e0423504 --- /dev/null +++ b/runsc/dockerutil/BUILD @@ -0,0 +1,15 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +package(licenses = ["notice"]) + +go_library( + name = "dockerutil", + testonly = 1, + srcs = ["dockerutil.go"], + importpath = "gvisor.dev/gvisor/runsc/dockerutil", + visibility = ["//:sandbox"], + deps = [ + "//runsc/testutil", + "@com_github_kr_pty//:go_default_library", + ], +) diff --git a/runsc/test/testutil/docker.go b/runsc/dockerutil/dockerutil.go index 94e625259..41f5fe1e8 100644 --- a/runsc/test/testutil/docker.go +++ b/runsc/dockerutil/dockerutil.go @@ -12,9 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -package testutil +// Package dockerutil is a collection of utility functions, primarily for +// testing. +package dockerutil import ( + "encoding/json" "flag" "fmt" "io/ioutil" @@ -29,26 +32,13 @@ import ( "time" "github.com/kr/pty" + "gvisor.dev/gvisor/runsc/testutil" ) -var runtimeType = flag.String("runtime-type", "", "specify which runtime to use: kvm, hostnet, overlay") - -func getRuntime() string { - r, ok := os.LookupEnv("RUNSC_RUNTIME") - if !ok { - r = "runsc-test" - } - if *runtimeType != "" { - r += "-" + *runtimeType - } - return r -} - -// IsPauseResumeSupported returns true if Pause/Resume is supported by runtime. -func IsPauseResumeSupported() bool { - // Native host network stack can't be saved. - return !strings.Contains(getRuntime(), "hostnet") -} +var ( + runtime = flag.String("runtime", "runsc", "specify which runtime to use") + config = flag.String("config_path", "/etc/docker/daemon.json", "configuration file for reading paths") +) // EnsureSupportedDockerVersion checks if correct docker is installed. func EnsureSupportedDockerVersion() { @@ -69,6 +59,48 @@ func EnsureSupportedDockerVersion() { } } +// RuntimePath returns the binary path for the current runtime. +func RuntimePath() (string, error) { + // Read the configuration data; the file must exist. + configBytes, err := ioutil.ReadFile(*config) + if err != nil { + return "", err + } + + // Unmarshal the configuration. + c := make(map[string]interface{}) + if err := json.Unmarshal(configBytes, &c); err != nil { + return "", err + } + + // Decode the expected configuration. + r, ok := c["runtimes"] + if !ok { + return "", fmt.Errorf("no runtimes declared: %v", c) + } + rs, ok := r.(map[string]interface{}) + if !ok { + // The runtimes are not a map. + return "", fmt.Errorf("unexpected format: %v", c) + } + r, ok = rs[*runtime] + if !ok { + // The expected runtime is not declared. + return "", fmt.Errorf("runtime %q not found: %v", *runtime, c) + } + rs, ok = r.(map[string]interface{}) + if !ok { + // The runtime is not a map. + return "", fmt.Errorf("unexpected format: %v", c) + } + p, ok := rs["path"].(string) + if !ok { + // The runtime does not declare a path. + return "", fmt.Errorf("unexpected format: %v", c) + } + return p, nil +} + // MountMode describes if the mount should be ro or rw. type MountMode int @@ -113,7 +145,7 @@ func PrepareFiles(names ...string) (string, error) { for _, name := range names { src := getLocalPath(name) dst := path.Join(dir, name) - if err := Copy(src, dst); err != nil { + if err := testutil.Copy(src, dst); err != nil { return "", fmt.Errorf("testutil.Copy(%q, %q) failed: %v", src, dst, err) } } @@ -163,7 +195,10 @@ type Docker struct { // MakeDocker sets up the struct for a Docker container. // Names of containers will be unique. func MakeDocker(namePrefix string) Docker { - return Docker{Name: RandomName(namePrefix), Runtime: getRuntime()} + return Docker{ + Name: testutil.RandomName(namePrefix), + Runtime: *runtime, + } } // logDockerID logs a container id, which is needed to find container runsc logs. diff --git a/runsc/main.go b/runsc/main.go index 70f06dbb8..0ff68160d 100644 --- a/runsc/main.go +++ b/runsc/main.go @@ -88,6 +88,11 @@ func main() { subcommands.Register(help, "") subcommands.Register(subcommands.FlagsCommand(), "") + // Installation helpers. + const helperGroup = "helpers" + subcommands.Register(new(cmd.Install), helperGroup) + subcommands.Register(new(cmd.Uninstall), helperGroup) + // Register user-facing runsc commands. subcommands.Register(new(cmd.Checkpoint), "") subcommands.Register(new(cmd.Create), "") diff --git a/runsc/test/BUILD b/runsc/test/BUILD deleted file mode 100644 index e69de29bb..000000000 --- a/runsc/test/BUILD +++ /dev/null diff --git a/runsc/test/README.md b/runsc/test/README.md deleted file mode 100644 index f22a8e017..000000000 --- a/runsc/test/README.md +++ /dev/null @@ -1,24 +0,0 @@ -# Tests - -The tests defined under this path are verifying functionality beyond what unit -tests can cover, e.g. integration and end to end tests. Due to their nature, -they may need extra setup in the test machine and extra configuration to run. - -- **integration:** defines integration tests that uses `docker run` to test - functionality. -- **image:** basic end to end test for popular images. -- **root:** tests that require to be run as root. -- **testutil:** utilities library to support the tests. - -The following setup steps are required in order to run these tests: - - `./runsc/test/install.sh [--runtime <name>]` - -The tests expect the runtime name to be provided in the `RUNSC_RUNTIME` -environment variable (default: `runsc-test`). To run the tests execute: - -``` -bazel test --test_env=RUNSC_RUNTIME=runsc-test \ - //runsc/test/image:image_test \ - //runsc/test/integration:integration_test -``` diff --git a/runsc/test/install.sh b/runsc/test/install.sh deleted file mode 100755 index 8f05dea20..000000000 --- a/runsc/test/install.sh +++ /dev/null @@ -1,93 +0,0 @@ -#!/bin/bash - -# Copyright 2018 The gVisor 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. - -# Fail on any error -set -e - -# Defaults -declare runtime=runsc-test -declare uninstall=0 - -function findExe() { - local exe=${1} - - local path=$(find bazel-bin/runsc -type f -executable -name "${exe}" | head -n1) - if [[ "${path}" == "" ]]; then - echo "Location of ${exe} not found in bazel-bin" >&2 - exit 1 - fi - echo "${path}" -} - -while [[ $# -gt 0 ]]; do - case "$1" in - --runtime) - shift - [ "$#" -le 0 ] && echo "No runtime provided" && exit 1 - runtime=$1 - ;; - -u) - uninstall=1 - ;; - *) - echo "Unknown option: ${1}" - echo "" - echo "Usage: ${0} [--runtime <name>] [-u]" - echo " --runtime sets the runtime name, default: runsc-test" - echo " -u uninstall the runtime" - exit 1 - esac - shift -done - -# Find location of executables. -declare -r dockercfg=$(findExe dockercfg) -[[ "${dockercfg}" == "" ]] && exit 1 - -declare runsc=$(findExe runsc) -[[ "${runsc}" == "" ]] && exit 1 - -if [[ ${uninstall} == 0 ]]; then - rm -rf /tmp/${runtime} - mkdir -p /tmp/${runtime} - cp "${runsc}" /tmp/${runtime}/runsc - runsc=/tmp/${runtime}/runsc - - # Make tmp dir and runsc binary readable and executable to all users, since it - # will run in an empty user namespace. - chmod a+rx "${runsc}" $(dirname "${runsc}") - - # Make log dir executable and writable to all users for the same reason. - declare logdir=/tmp/"${runtime?}/logs" - mkdir -p "${logdir}" - sudo -n chmod a+wx "${logdir}" - - declare -r args="--debug-log '${logdir}/' --debug --strace --log-packets" - # experimental is needed to checkpoint/restore. - sudo -n "${dockercfg}" --experimental=true runtime-add "${runtime}" "${runsc}" ${args} - sudo -n "${dockercfg}" runtime-add "${runtime}"-kvm "${runsc}" --platform=kvm ${args} - sudo -n "${dockercfg}" runtime-add "${runtime}"-hostnet "${runsc}" --network=host ${args} - sudo -n "${dockercfg}" runtime-add "${runtime}"-overlay "${runsc}" --overlay ${args} - -else - sudo -n "${dockercfg}" runtime-rm "${runtime}" - sudo -n "${dockercfg}" runtime-rm "${runtime}"-kvm - sudo -n "${dockercfg}" runtime-rm "${runtime}"-hostnet - sudo -n "${dockercfg}" runtime-rm "${runtime}"-overlay -fi - -echo "Restarting docker service..." -sudo -n /etc/init.d/docker restart diff --git a/runsc/test/testutil/testutil_race.go b/runsc/test/testutil/testutil_race.go deleted file mode 100644 index 86db6ffa1..000000000 --- a/runsc/test/testutil/testutil_race.go +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2018 The gVisor 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. - -// +build race - -package testutil - -func init() { - RaceEnabled = true -} diff --git a/runsc/test/testutil/BUILD b/runsc/testutil/BUILD index 327e7ca4d..d44ebc906 100644 --- a/runsc/test/testutil/BUILD +++ b/runsc/testutil/BUILD @@ -4,19 +4,14 @@ package(licenses = ["notice"]) go_library( name = "testutil", - srcs = [ - "crictl.go", - "docker.go", - "testutil.go", - "testutil_race.go", - ], - importpath = "gvisor.dev/gvisor/runsc/test/testutil", + testonly = 1, + srcs = ["testutil.go"], + importpath = "gvisor.dev/gvisor/runsc/testutil", visibility = ["//:sandbox"], deps = [ "//runsc/boot", "//runsc/specutils", "@com_github_cenkalti_backoff//:go_default_library", - "@com_github_kr_pty//:go_default_library", "@com_github_opencontainers_runtime-spec//specs-go:go_default_library", ], ) diff --git a/runsc/test/testutil/testutil.go b/runsc/testutil/testutil.go index 4a3dfa0e3..57ab73d97 100644 --- a/runsc/test/testutil/testutil.go +++ b/runsc/testutil/testutil.go @@ -18,8 +18,10 @@ package testutil import ( "bufio" "context" + "debug/elf" "encoding/base32" "encoding/json" + "flag" "fmt" "io" "io/ioutil" @@ -42,12 +44,18 @@ import ( "gvisor.dev/gvisor/runsc/specutils" ) +var ( + checkpoint = flag.Bool("checkpoint", true, "control checkpoint/restore support") +) + func init() { rand.Seed(time.Now().UnixNano()) } -// RaceEnabled is set to true if it was built with '--race' option. -var RaceEnabled = false +// IsCheckpointSupported returns the relevant command line flag. +func IsCheckpointSupported() bool { + return *checkpoint +} // TmpDir returns the absolute path to a writable directory that can be used as // scratch by the test. @@ -191,14 +199,11 @@ func SetupRootDir() (string, error) { // SetupContainer creates a bundle and root dir for the container, generates a // test config, and writes the spec to config.json in the bundle dir. func SetupContainer(spec *specs.Spec, conf *boot.Config) (rootDir, bundleDir string, err error) { - // Setup root dir if one hasn't been provided. - if len(conf.RootDir) == 0 { - rootDir, err = SetupRootDir() - if err != nil { - return "", "", err - } - conf.RootDir = rootDir + rootDir, err = SetupRootDir() + if err != nil { + return "", "", err } + conf.RootDir = rootDir bundleDir, err = SetupBundleDir(spec) return rootDir, bundleDir, err } @@ -419,3 +424,17 @@ func WriteTmpFile(pattern, text string) (string, error) { func RandomName(prefix string) string { return fmt.Sprintf("%s-%06d", prefix, rand.Int31n(1000000)) } + +// IsStatic returns true iff the given file is a static binary. +func IsStatic(filename string) (bool, error) { + f, err := elf.Open(filename) + if err != nil { + return false, err + } + for _, prog := range f.Progs { + if prog.Type == elf.PT_INTERP { + return false, nil // Has interpreter. + } + } + return true, nil +} diff --git a/runsc/tools/dockercfg/BUILD b/runsc/tools/dockercfg/BUILD deleted file mode 100644 index 5cff917ed..000000000 --- a/runsc/tools/dockercfg/BUILD +++ /dev/null @@ -1,10 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_binary") - -package(licenses = ["notice"]) - -go_binary( - name = "dockercfg", - srcs = ["dockercfg.go"], - visibility = ["//visibility:public"], - deps = ["@com_github_google_subcommands//:go_default_library"], -) diff --git a/runsc/tools/dockercfg/dockercfg.go b/runsc/tools/dockercfg/dockercfg.go deleted file mode 100644 index eb9dbd421..000000000 --- a/runsc/tools/dockercfg/dockercfg.go +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright 2018 The gVisor 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. - -// Helper tool to configure Docker daemon. -package main - -import ( - "context" - "encoding/json" - "fmt" - "io/ioutil" - "log" - "os" - - "flag" - "github.com/google/subcommands" -) - -var ( - configFile = flag.String("config_file", "/etc/docker/daemon.json", "path to Docker daemon config file") - experimental = flag.Bool("experimental", false, "enable experimental features") -) - -func main() { - subcommands.Register(subcommands.HelpCommand(), "") - subcommands.Register(subcommands.FlagsCommand(), "") - subcommands.Register(&runtimeAdd{}, "") - subcommands.Register(&runtimeRemove{}, "") - - // All subcommands must be registered before flag parsing. - flag.Parse() - - exitCode := subcommands.Execute(context.Background()) - os.Exit(int(exitCode)) -} - -type runtime struct { - Path string `json:"path,omitempty"` - RuntimeArgs []string `json:"runtimeArgs,omitempty"` -} - -// runtimeAdd implements subcommands.Command. -type runtimeAdd struct { -} - -// Name implements subcommands.Command.Name. -func (*runtimeAdd) Name() string { - return "runtime-add" -} - -// Synopsis implements subcommands.Command.Synopsis. -func (*runtimeAdd) Synopsis() string { - return "adds a runtime to docker daemon configuration" -} - -// Usage implements subcommands.Command.Usage. -func (*runtimeAdd) Usage() string { - return `runtime-add [flags] <name> <path> [args...] -- if provided, args are passed as arguments to the runtime -` -} - -// SetFlags implements subcommands.Command.SetFlags. -func (*runtimeAdd) SetFlags(*flag.FlagSet) { -} - -// Execute implements subcommands.Command.Execute. -func (r *runtimeAdd) Execute(_ context.Context, f *flag.FlagSet, args ...interface{}) subcommands.ExitStatus { - if f.NArg() < 2 { - f.Usage() - return subcommands.ExitUsageError - } - name := f.Arg(0) - path := f.Arg(1) - runtimeArgs := f.Args()[2:] - - fmt.Printf("Adding runtime %q to file %q\n", name, *configFile) - c, err := readConfig(*configFile) - if err != nil { - log.Fatalf("Error reading config file %q: %v", *configFile, err) - } - - var rts map[string]interface{} - if i, ok := c["runtimes"]; ok { - rts = i.(map[string]interface{}) - } else { - rts = make(map[string]interface{}) - c["runtimes"] = rts - } - if *experimental { - c["experimental"] = true - } - rts[name] = runtime{Path: path, RuntimeArgs: runtimeArgs} - - if err := writeConfig(c, *configFile); err != nil { - log.Fatalf("Error writing config file %q: %v", *configFile, err) - } - return subcommands.ExitSuccess -} - -// runtimeRemove implements subcommands.Command. -type runtimeRemove struct { -} - -// Name implements subcommands.Command.Name. -func (*runtimeRemove) Name() string { - return "runtime-rm" -} - -// Synopsis implements subcommands.Command.Synopsis. -func (*runtimeRemove) Synopsis() string { - return "removes a runtime from docker daemon configuration" -} - -// Usage implements subcommands.Command.Usage. -func (*runtimeRemove) Usage() string { - return `runtime-rm [flags] <name> -` -} - -// SetFlags implements subcommands.Command.SetFlags. -func (*runtimeRemove) SetFlags(*flag.FlagSet) { -} - -// Execute implements subcommands.Command.Execute. -func (r *runtimeRemove) Execute(_ context.Context, f *flag.FlagSet, args ...interface{}) subcommands.ExitStatus { - if f.NArg() != 1 { - f.Usage() - return subcommands.ExitUsageError - } - name := f.Arg(0) - - fmt.Printf("Removing runtime %q from file %q\n", name, *configFile) - c, err := readConfig(*configFile) - if err != nil { - log.Fatalf("Error reading config file %q: %v", *configFile, err) - } - - var rts map[string]interface{} - if i, ok := c["runtimes"]; ok { - rts = i.(map[string]interface{}) - } else { - log.Fatalf("runtime %q not found", name) - } - if _, ok := rts[name]; !ok { - log.Fatalf("runtime %q not found", name) - } - delete(rts, name) - - if err := writeConfig(c, *configFile); err != nil { - log.Fatalf("Error writing config file %q: %v", *configFile, err) - } - return subcommands.ExitSuccess -} - -func readConfig(path string) (map[string]interface{}, error) { - configBytes, err := ioutil.ReadFile(path) - if err != nil && !os.IsNotExist(err) { - return nil, err - } - c := make(map[string]interface{}) - if len(configBytes) > 0 { - if err := json.Unmarshal(configBytes, &c); err != nil { - return nil, err - } - } - return c, nil -} - -func writeConfig(c map[string]interface{}, path string) error { - b, err := json.MarshalIndent(c, "", " ") - if err != nil { - return err - } - - if err := os.Rename(path, path+"~"); err != nil && !os.IsNotExist(err) { - return fmt.Errorf("error renaming config file %q: %v", path, err) - } - if err := ioutil.WriteFile(path, b, 0644); err != nil { - return fmt.Errorf("error writing config file %q: %v", path, err) - } - return nil -} diff --git a/scripts/build.sh b/scripts/build.sh new file mode 100755 index 000000000..dae3460af --- /dev/null +++ b/scripts/build.sh @@ -0,0 +1,62 @@ +#!/bin/bash + +# Copyright 2018 The gVisor 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. + +source $(dirname $0)/common.sh + +# Build runsc. +runsc=$(build -c opt //runsc) + +# Build packages. +pkg=$(build -c opt --host_force_python=py2 //runsc:debian) + +# Build a repository, if the key is available. +if [[ -v KOKORO_REPO_KEY ]]; then + repo=$(tools/make_repository.sh "${KOKORO_REPO_KEY}" gvisor-bot@google.com) +fi + +# Install installs artifacts. +install() { + mkdir -p $1 + cp "${runsc}" "$1"/runsc + sha512sum "$1"/runsc | awk '{print $1 " runsc"}' > "$1"/runsc.sha512 + if [[ -v repo ]]; then + cp -a "${repo}" "${latest_dir}"/repo + fi +} + +# Move the runsc binary into "latest" directory, and also a directory with the +# current date. If the current commit happens to correpond to a tag, then we +# will also move everything into a directory named after the given tag. +if [[ -v KOKORO_ARTIFACTS_DIR ]]; then + if [[ "${KOKORO_BUILD_NIGHTLY}" == "true" ]]; then + # The "latest" directory and current date. + install "${KOKORO_ARTIFACTS_DIR}/nightly/latest" + install "${KOKORO_ARTIFACTS_DIR}/nightly/$(date -Idate)" + else + # Is it a tagged release? Build that instead. In that case, we also try to + # update the base release directory, in case this is an update. Finally, we + # update the "release" directory, which has the last released version. + tag="$(git describe --exact-match --tags HEAD)" + if ! [[ -z "${tag}" ]]; then + install "${KOKORO_ARTIFACTS_DIR}/${tag}" + base=$(echo "${tag}" | cut -d'.' -f1) + if [[ "${base}" != "${tag}" ]]; then + install "${KOKORO_ARTIFACTS_DIR}/${base}" + fi + install "${KOKORO_ARTIFACTS_DIR}/release" + fi + fi +fi diff --git a/scripts/common.sh b/scripts/common.sh new file mode 100755 index 000000000..f2b9e24d8 --- /dev/null +++ b/scripts/common.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +# Copyright 2019 The gVisor 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. + +set -xeo pipefail + +if [[ -f $(dirname $0)/common_google.sh ]]; then + source $(dirname $0)/common_google.sh +else + source $(dirname $0)/common_bazel.sh +fi diff --git a/scripts/common_bazel.sh b/scripts/common_bazel.sh new file mode 100755 index 000000000..42248cb25 --- /dev/null +++ b/scripts/common_bazel.sh @@ -0,0 +1,77 @@ +#!/bin/bash + +# Copyright 2019 The gVisor 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. + +# Install the latest version of Bazel and log the version. +(which use_bazel.sh && use_bazel.sh latest) || which bazel +bazel version + +# Switch into the workspace; only necessary if run with kokoro. +if [[ -v KOKORO_GIT_COMMIT ]] && [[ -d git/repo ]]; then + cd git/repo +elif [[ -v KOKORO_GIT_COMMIT ]] && [[ -d github/repo ]]; then + cd github/repo +fi + +# Set the standard bazel flags. +declare -r BAZEL_FLAGS=( + "--show_timestamps" + "--test_output=errors" + "--keep_going" + "--verbose_failures=true" +) +if [[ -v KOKORO_BAZEL_AUTH_CREDENTIAL ]] || [[ -v RBE_PROJECT_ID ]]; then + declare -r RBE_PROJECT_ID="${RBE_PROJECT_ID:-gvisor-rbe}" + declare -r BAZEL_RBE_FLAGS=( + "--config=remote" + "--project_id=${RBE_PROJECT_ID}" + "--remote_instance_name=projects/${RBE_PROJECT_ID}/instances/default_instance" + ) +fi +if [[ -v KOKORO_BAZEL_AUTH_CREDENTIAL ]]; then + declare -r BAZEL_RBE_AUTH_FLAGS=( + "--auth_credentials=${KOKORO_BAZEL_AUTH_CREDENTIAL}" + ) +fi + +# Wrap bazel. +function build() { + bazel build "${BAZEL_RBE_FLAGS[@]}" "${BAZEL_RBE_AUTH_FLAGS[@]}" "${BAZEL_FLAGS[@]}" "$@" +} + +function test() { + (bazel test "${BAZEL_RBE_FLAGS[@]}" "${BAZEL_RBE_AUTH_FLAGS[@]}" "${BAZEL_FLAGS[@]}" "$@" && rc=0) || rc=$? + + # Zip out everything into a convenient form. + if [[ -v KOKORO_ARTIFACTS_DIR ]]; then + find -L "bazel-testlogs" -name "test.xml" -o -name "test.log" -o -name "outputs.zip" | + tar --create --files-from - --transform 's/test\./sponge_log./' | + tar --extract --directory ${KOKORO_ARTIFACTS_DIR} + fi + + return $rc +} + +function run() { + local binary=$1 + shift + bazel run "${binary}" -- "$@" +} + +function run_as_root() { + local binary=$1 + shift + bazel run --run_under="sudo" "${binary}" -- "$@" +} diff --git a/scripts/do_tests.sh b/scripts/do_tests.sh new file mode 100755 index 000000000..a3a387c37 --- /dev/null +++ b/scripts/do_tests.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +# Copyright 2019 The gVisor 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. + +source $(dirname $0)/common.sh + +# Build runsc. +build //runsc + +# run runsc do without root privileges. +run //runsc --rootless do true +run //runsc --rootless --network=none do true + +# run runsc do with root privileges. +run_as_root //runsc do true diff --git a/scripts/docker_tests.sh b/scripts/docker_tests.sh new file mode 100755 index 000000000..d6b18a35b --- /dev/null +++ b/scripts/docker_tests.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +# Copyright 2019 The gVisor 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. + +source $(dirname $0)/common.sh + +# Install the runtime and perform basic tests. +run_as_root //runsc install --experimental=true -- --debug --strace --log-packets +sudo systemctl restart docker +test //test/image:image_test //test/e2e:integration_test diff --git a/scripts/go.sh b/scripts/go.sh new file mode 100755 index 000000000..e49d76c6d --- /dev/null +++ b/scripts/go.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +# Copyright 2019 The gVisor 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. + +source $(dirname $0)/common.sh + +# Build the go path. +build :gopath + +# Build the synthetic branch. +tools/go_branch.sh + +# Checkout the new branch. +git checkout go && git clean -f + +# Build everything. +go build ./... + +# Push, if required. +if [[ "${KOKORO_GO_PUSH}" == "true" ]]; then + git push origin go:go +fi diff --git a/scripts/hostnet_tests.sh b/scripts/hostnet_tests.sh new file mode 100755 index 000000000..0631c5510 --- /dev/null +++ b/scripts/hostnet_tests.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +# Copyright 2019 The gVisor 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. + +source $(dirname $0)/common.sh + +# Install the runtime and perform basic tests. +run_as_root //runsc install --experimental=true -- --debug --strace --log-packets --network=host +sudo systemctl restart docker +test --test_arg=-checkpoint=false //test/image:image_test //test/e2e:integration_test diff --git a/scripts/kvm_tests.sh b/scripts/kvm_tests.sh new file mode 100755 index 000000000..5cb7aa007 --- /dev/null +++ b/scripts/kvm_tests.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +# Copyright 2019 The gVisor 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. + +source $(dirname $0)/common.sh + +# Ensure that KVM is loaded, and we can use it. +(lsmod | grep -E '^(kvm_intel|kvm_amd)') || sudo modprobe kvm +sudo chmod a+rw /dev/kvm + +# Run all KVM-tagged tests (locally). +test --test_strategy=standalone --test_tag_filters=requires-kvm //... +test --test_strategy=standalone //pkg/sentry/platform/kvm:kvm_test + +# Install the KVM runtime and run all integration tests. +run_as_root //runsc install --experimental=true -- --debug --strace --log-packets --platform=kvm +sudo systemctl restart docker +test --test_strategy=standalone //test/image:image_test //test/e2e:integration_test diff --git a/scripts/make_tests.sh b/scripts/make_tests.sh new file mode 100755 index 000000000..0fa1248be --- /dev/null +++ b/scripts/make_tests.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +# Copyright 2019 The gVisor 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. + +source $(dirname $0)/common.sh + +top_level=$(git rev-parse --show-toplevel 2>/dev/null) +[[ $? -eq 0 ]] && cd "${top_level}" || exit 1 + +make +make runsc +make bazel-shutdown diff --git a/scripts/overlay_tests.sh b/scripts/overlay_tests.sh new file mode 100755 index 000000000..651a51f70 --- /dev/null +++ b/scripts/overlay_tests.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +# Copyright 2019 The gVisor 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. + +source $(dirname $0)/common.sh + +# Install the runtime and perform basic tests. +run_as_root //runsc install --experimental=true -- --debug --strace --log-packets --overlay +sudo systemctl restart docker +test //test/image:image_test //test/e2e:integration_test diff --git a/scripts/release.sh b/scripts/release.sh new file mode 100755 index 000000000..422319500 --- /dev/null +++ b/scripts/release.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +# Copyright 2018 The gVisor 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. + +source $(dirname $0)/common.sh + +# Tag a release only if provided. +if ! [[ -v KOKORO_RELEASE_COMMIT ]]; then + echo "No KOKORO_RELEASE_COMMIT provided." >&2 + exit 1 +fi +if ! [[ -v KOKORO_RELEASE_TAG ]]; then + echo "No KOKORO_RELEASE_TAG provided." >&2 + exit 1 +fi + +# Ensure we have an appropriate configuration for the tag. +git config --get user.name || git config user.name "gVisor-bot" +git config --get user.email || git config user.email "gvisor-bot@google.com" + +# Run the release tool, which pushes to the origin repository. +tools/tag_release.sh "${KOKORO_RELEASE_COMMIT}" "${KOKORO_RELEASE_TAG}" diff --git a/scripts/root_tests.sh b/scripts/root_tests.sh new file mode 100755 index 000000000..e42c0e3ec --- /dev/null +++ b/scripts/root_tests.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +# Copyright 2019 The gVisor 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. + +source $(dirname $0)/common.sh + +# Reinstall the latest containerd shim. +declare -r base="https://storage.googleapis.com/cri-containerd-staging/gvisor-containerd-shim" +declare -r latest=$(mktemp --tmpdir gvisor-containerd-shim-latest.XXXXXX) +declare -r shim_path=$(mktemp --tmpdir gvisor-containerd-shim.XXXXXX) +wget --no-verbose "${base}"/latest -O ${latest} +wget --no-verbose "${base}"/gvisor-containerd-shim-$(cat ${latest}) -O ${shim_path} +chmod +x ${shim_path} +sudo mv ${shim_path} /usr/local/bin/gvisor-containerd-shim + +# Run the tests that require root. +run_as_root //runsc install --experimental=true -- --debug --strace --log-packets +sudo systemctl restart docker +run_as_root //test/root:root_test diff --git a/scripts/simple_tests.sh b/scripts/simple_tests.sh new file mode 100755 index 000000000..585216aae --- /dev/null +++ b/scripts/simple_tests.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +# Copyright 2019 The gVisor 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. + +source $(dirname $0)/common.sh + +# Run all simple tests (locally). +test //pkg/... //runsc/... //tools/... diff --git a/scripts/syscall_tests.sh b/scripts/syscall_tests.sh new file mode 100755 index 000000000..a131b2d50 --- /dev/null +++ b/scripts/syscall_tests.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +# Copyright 2019 The gVisor 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. + +source $(dirname $0)/common.sh + +# Run all ptrace-variants of the system call tests. +test --test_tag_filters=runsc_ptrace //test/syscalls/... diff --git a/test/README.md b/test/README.md new file mode 100644 index 000000000..09c36b461 --- /dev/null +++ b/test/README.md @@ -0,0 +1,18 @@ +# Tests + +The tests defined under this path are verifying functionality beyond what unit +tests can cover, e.g. integration and end to end tests. Due to their nature, +they may need extra setup in the test machine and extra configuration to run. + +- **syscalls**: system call tests use a local runner, and do not require + additional configuration in the machine. +- **integration:** defines integration tests that uses `docker run` to test + functionality. +- **image:** basic end to end test for popular images. These require the same + setup as integration tests. +- **root:** tests that require to be run as root. +- **util:** utilities library to support the tests. + +For the above noted cases, the relevant runtime must be installed via `runsc +install` before running. This is handled automatically by the test scripts in +the `kokoro` directory. diff --git a/runsc/test/integration/BUILD b/test/e2e/BUILD index 12065617c..99442cffb 100644 --- a/runsc/test/integration/BUILD +++ b/test/e2e/BUILD @@ -1,9 +1,8 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") -load("//runsc/test:build_defs.bzl", "runtime_test") +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(licenses = ["notice"]) -runtime_test( +go_test( name = "integration_test", size = "large", srcs = [ @@ -17,14 +16,16 @@ runtime_test( "manual", "local", ], + visibility = ["//:sandbox"], deps = [ "//pkg/abi/linux", - "//runsc/test/testutil", + "//runsc/dockerutil", + "//runsc/testutil", ], ) go_library( name = "integration", srcs = ["integration.go"], - importpath = "gvisor.dev/gvisor/runsc/test/integration", + importpath = "gvisor.dev/gvisor/test/integration", ) diff --git a/runsc/test/integration/exec_test.go b/test/e2e/exec_test.go index 993136f96..ce2c4f689 100644 --- a/runsc/test/integration/exec_test.go +++ b/test/e2e/exec_test.go @@ -12,17 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Package image provides end-to-end integration tests for runsc. These tests require -// docker and runsc to be installed on the machine. To set it up, run: +// Package image provides end-to-end integration tests for runsc. These tests +// require docker and runsc to be installed on the machine. // -// ./runsc/test/install.sh [--runtime <name>] -// -// The tests expect the runtime name to be provided in the RUNSC_RUNTIME -// environment variable (default: runsc-test). -// -// Each test calls docker commands to start up a container, and tests that it is -// behaving properly, with various runsc commands. The container is killed and deleted -// at the end. +// Each test calls docker commands to start up a container, and tests that it +// is behaving properly, with various runsc commands. The container is killed +// and deleted at the end. package integration @@ -35,14 +30,14 @@ import ( "time" "gvisor.dev/gvisor/pkg/abi/linux" - "gvisor.dev/gvisor/runsc/test/testutil" + "gvisor.dev/gvisor/runsc/dockerutil" ) func TestExecCapabilities(t *testing.T) { - if err := testutil.Pull("alpine"); err != nil { + if err := dockerutil.Pull("alpine"); err != nil { t.Fatalf("docker pull failed: %v", err) } - d := testutil.MakeDocker("exec-test") + d := dockerutil.MakeDocker("exec-test") // Start the container. if err := d.Run("alpine", "sh", "-c", "cat /proc/self/status; sleep 100"); err != nil { @@ -84,10 +79,10 @@ func TestExecCapabilities(t *testing.T) { } func TestExecJobControl(t *testing.T) { - if err := testutil.Pull("alpine"); err != nil { + if err := dockerutil.Pull("alpine"); err != nil { t.Fatalf("docker pull failed: %v", err) } - d := testutil.MakeDocker("exec-job-control-test") + d := dockerutil.MakeDocker("exec-job-control-test") // Start the container. if err := d.Run("alpine", "sleep", "1000"); err != nil { @@ -140,10 +135,10 @@ func TestExecJobControl(t *testing.T) { // Test that failure to exec returns proper error message. func TestExecError(t *testing.T) { - if err := testutil.Pull("alpine"); err != nil { + if err := dockerutil.Pull("alpine"); err != nil { t.Fatalf("docker pull failed: %v", err) } - d := testutil.MakeDocker("exec-error-test") + d := dockerutil.MakeDocker("exec-error-test") // Start the container. if err := d.Run("alpine", "sleep", "1000"); err != nil { diff --git a/runsc/test/integration/integration.go b/test/e2e/integration.go index 4cd5f6c24..4cd5f6c24 100644 --- a/runsc/test/integration/integration.go +++ b/test/e2e/integration.go diff --git a/runsc/test/integration/integration_test.go b/test/e2e/integration_test.go index 7cef4b9dd..7cc0de129 100644 --- a/runsc/test/integration/integration_test.go +++ b/test/e2e/integration_test.go @@ -18,10 +18,11 @@ // behaving properly, with various runsc commands. The container is killed and // deleted at the end. // -// Setup instruction in runsc/test/README.md. +// Setup instruction in test/README.md. package integration import ( + "flag" "fmt" "net" "net/http" @@ -32,7 +33,8 @@ import ( "testing" "time" - "gvisor.dev/gvisor/runsc/test/testutil" + "gvisor.dev/gvisor/runsc/dockerutil" + "gvisor.dev/gvisor/runsc/testutil" ) // httpRequestSucceeds sends a request to a given url and checks that the status is OK. @@ -51,10 +53,10 @@ func httpRequestSucceeds(client http.Client, server string, port int) error { // TestLifeCycle tests a basic Create/Start/Stop docker container life cycle. func TestLifeCycle(t *testing.T) { - if err := testutil.Pull("nginx"); err != nil { + if err := dockerutil.Pull("nginx"); err != nil { t.Fatal("docker pull failed:", err) } - d := testutil.MakeDocker("lifecycle-test") + d := dockerutil.MakeDocker("lifecycle-test") if err := d.Create("-p", "80", "nginx"); err != nil { t.Fatal("docker create failed:", err) } @@ -87,15 +89,15 @@ func TestLifeCycle(t *testing.T) { func TestPauseResume(t *testing.T) { const img = "gcr.io/gvisor-presubmit/python-hello" - if !testutil.IsPauseResumeSupported() { - t.Log("Pause/resume is not supported, skipping test.") + if !testutil.IsCheckpointSupported() { + t.Log("Checkpoint is not supported, skipping test.") return } - if err := testutil.Pull(img); err != nil { + if err := dockerutil.Pull(img); err != nil { t.Fatal("docker pull failed:", err) } - d := testutil.MakeDocker("pause-resume-test") + d := dockerutil.MakeDocker("pause-resume-test") if err := d.Run("-p", "8080", img); err != nil { t.Fatalf("docker run failed: %v", err) } @@ -151,14 +153,15 @@ func TestPauseResume(t *testing.T) { func TestCheckpointRestore(t *testing.T) { const img = "gcr.io/gvisor-presubmit/python-hello" - if !testutil.IsPauseResumeSupported() { + if !testutil.IsCheckpointSupported() { t.Log("Pause/resume is not supported, skipping test.") return } - if err := testutil.Pull(img); err != nil { + + if err := dockerutil.Pull(img); err != nil { t.Fatal("docker pull failed:", err) } - d := testutil.MakeDocker("save-restore-test") + d := dockerutil.MakeDocker("save-restore-test") if err := d.Run("-p", "8080", img); err != nil { t.Fatalf("docker run failed: %v", err) } @@ -196,7 +199,7 @@ func TestCheckpointRestore(t *testing.T) { // Create client and server that talk to each other using the local IP. func TestConnectToSelf(t *testing.T) { - d := testutil.MakeDocker("connect-to-self-test") + d := dockerutil.MakeDocker("connect-to-self-test") // Creates server that replies "server" and exists. Sleeps at the end because // 'docker exec' gets killed if the init process exists before it can finish. @@ -228,10 +231,10 @@ func TestConnectToSelf(t *testing.T) { } func TestMemLimit(t *testing.T) { - if err := testutil.Pull("alpine"); err != nil { + if err := dockerutil.Pull("alpine"); err != nil { t.Fatal("docker pull failed:", err) } - d := testutil.MakeDocker("cgroup-test") + d := dockerutil.MakeDocker("cgroup-test") cmd := "cat /proc/meminfo | grep MemTotal: | awk '{print $2}'" out, err := d.RunFg("--memory=500MB", "alpine", "sh", "-c", cmd) if err != nil { @@ -258,10 +261,10 @@ func TestMemLimit(t *testing.T) { } func TestNumCPU(t *testing.T) { - if err := testutil.Pull("alpine"); err != nil { + if err := dockerutil.Pull("alpine"); err != nil { t.Fatal("docker pull failed:", err) } - d := testutil.MakeDocker("cgroup-test") + d := dockerutil.MakeDocker("cgroup-test") cmd := "cat /proc/cpuinfo | grep 'processor.*:' | wc -l" out, err := d.RunFg("--cpuset-cpus=0", "alpine", "sh", "-c", cmd) if err != nil { @@ -280,10 +283,10 @@ func TestNumCPU(t *testing.T) { // TestJobControl tests that job control characters are handled properly. func TestJobControl(t *testing.T) { - if err := testutil.Pull("alpine"); err != nil { + if err := dockerutil.Pull("alpine"); err != nil { t.Fatalf("docker pull failed: %v", err) } - d := testutil.MakeDocker("job-control-test") + d := dockerutil.MakeDocker("job-control-test") // Start the container with an attached PTY. _, ptmx, err := d.RunWithPty("alpine", "sh") @@ -328,10 +331,10 @@ func TestJobControl(t *testing.T) { // TestTmpFile checks that files inside '/tmp' are not overridden. In addition, // it checks that working dir is created if it doesn't exit. func TestTmpFile(t *testing.T) { - if err := testutil.Pull("alpine"); err != nil { + if err := dockerutil.Pull("alpine"); err != nil { t.Fatal("docker pull failed:", err) } - d := testutil.MakeDocker("tmp-file-test") + d := dockerutil.MakeDocker("tmp-file-test") if err := d.Run("-w=/tmp/foo/bar", "--read-only", "alpine", "touch", "/tmp/foo/bar/file"); err != nil { t.Fatal("docker run failed:", err) } @@ -339,6 +342,7 @@ func TestTmpFile(t *testing.T) { } func TestMain(m *testing.M) { - testutil.EnsureSupportedDockerVersion() + dockerutil.EnsureSupportedDockerVersion() + flag.Parse() os.Exit(m.Run()) } diff --git a/runsc/test/integration/regression_test.go b/test/e2e/regression_test.go index fb68dda99..2488be383 100644 --- a/runsc/test/integration/regression_test.go +++ b/test/e2e/regression_test.go @@ -18,7 +18,7 @@ import ( "strings" "testing" - "gvisor.dev/gvisor/runsc/test/testutil" + "gvisor.dev/gvisor/runsc/dockerutil" ) // Test that UDS can be created using overlay when parent directory is in lower @@ -27,10 +27,10 @@ import ( // Prerequisite: the directory where the socket file is created must not have // been open for write before bind(2) is called. func TestBindOverlay(t *testing.T) { - if err := testutil.Pull("ubuntu:trusty"); err != nil { + if err := dockerutil.Pull("ubuntu:trusty"); err != nil { t.Fatal("docker pull failed:", err) } - d := testutil.MakeDocker("bind-overlay-test") + d := dockerutil.MakeDocker("bind-overlay-test") cmd := "nc -l -U /var/run/sock & p=$! && sleep 1 && echo foobar-asdf | nc -U /var/run/sock && wait $p" got, err := d.RunFg("ubuntu:trusty", "bash", "-c", cmd) diff --git a/runsc/test/image/BUILD b/test/image/BUILD index 58758fde5..09b0a0ad5 100644 --- a/runsc/test/image/BUILD +++ b/test/image/BUILD @@ -1,9 +1,8 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") -load("//runsc/test:build_defs.bzl", "runtime_test") +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") package(licenses = ["notice"]) -runtime_test( +go_test( name = "image_test", size = "large", srcs = [ @@ -21,11 +20,15 @@ runtime_test( "manual", "local", ], - deps = ["//runsc/test/testutil"], + visibility = ["//:sandbox"], + deps = [ + "//runsc/dockerutil", + "//runsc/testutil", + ], ) go_library( name = "image", srcs = ["image.go"], - importpath = "gvisor.dev/gvisor/runsc/test/image", + importpath = "gvisor.dev/gvisor/test/image", ) diff --git a/runsc/test/image/image.go b/test/image/image.go index 297f1ab92..297f1ab92 100644 --- a/runsc/test/image/image.go +++ b/test/image/image.go diff --git a/runsc/test/image/image_test.go b/test/image/image_test.go index ddaa2c13b..d0dcb1861 100644 --- a/runsc/test/image/image_test.go +++ b/test/image/image_test.go @@ -14,14 +14,15 @@ // Package image provides end-to-end image tests for runsc. -// Each test calls docker commands to start up a container, and tests that it is -// behaving properly, like connecting to a port or looking at the output. The -// container is killed and deleted at the end. +// Each test calls docker commands to start up a container, and tests that it +// is behaving properly, like connecting to a port or looking at the output. +// The container is killed and deleted at the end. // -// Setup instruction in runsc/test/README.md. +// Setup instruction in test/README.md. package image import ( + "flag" "fmt" "io/ioutil" "log" @@ -32,11 +33,12 @@ import ( "testing" "time" - "gvisor.dev/gvisor/runsc/test/testutil" + "gvisor.dev/gvisor/runsc/dockerutil" + "gvisor.dev/gvisor/runsc/testutil" ) func TestHelloWorld(t *testing.T) { - d := testutil.MakeDocker("hello-test") + d := dockerutil.MakeDocker("hello-test") if err := d.Run("hello-world"); err != nil { t.Fatalf("docker run failed: %v", err) } @@ -100,18 +102,18 @@ func testHTTPServer(t *testing.T, port int) { } func TestHttpd(t *testing.T) { - if err := testutil.Pull("httpd"); err != nil { + if err := dockerutil.Pull("httpd"); err != nil { t.Fatalf("docker pull failed: %v", err) } - d := testutil.MakeDocker("http-test") + d := dockerutil.MakeDocker("http-test") - dir, err := testutil.PrepareFiles("latin10k.txt") + dir, err := dockerutil.PrepareFiles("latin10k.txt") if err != nil { t.Fatalf("PrepareFiles() failed: %v", err) } // Start the container. - mountArg := testutil.MountArg(dir, "/usr/local/apache2/htdocs", testutil.ReadOnly) + mountArg := dockerutil.MountArg(dir, "/usr/local/apache2/htdocs", dockerutil.ReadOnly) if err := d.Run("-p", "80", mountArg, "httpd"); err != nil { t.Fatalf("docker run failed: %v", err) } @@ -132,18 +134,18 @@ func TestHttpd(t *testing.T) { } func TestNginx(t *testing.T) { - if err := testutil.Pull("nginx"); err != nil { + if err := dockerutil.Pull("nginx"); err != nil { t.Fatalf("docker pull failed: %v", err) } - d := testutil.MakeDocker("net-test") + d := dockerutil.MakeDocker("net-test") - dir, err := testutil.PrepareFiles("latin10k.txt") + dir, err := dockerutil.PrepareFiles("latin10k.txt") if err != nil { t.Fatalf("PrepareFiles() failed: %v", err) } // Start the container. - mountArg := testutil.MountArg(dir, "/usr/share/nginx/html", testutil.ReadOnly) + mountArg := dockerutil.MountArg(dir, "/usr/share/nginx/html", dockerutil.ReadOnly) if err := d.Run("-p", "80", mountArg, "nginx"); err != nil { t.Fatalf("docker run failed: %v", err) } @@ -164,10 +166,10 @@ func TestNginx(t *testing.T) { } func TestMysql(t *testing.T) { - if err := testutil.Pull("mysql"); err != nil { + if err := dockerutil.Pull("mysql"); err != nil { t.Fatalf("docker pull failed: %v", err) } - d := testutil.MakeDocker("mysql-test") + d := dockerutil.MakeDocker("mysql-test") // Start the container. if err := d.Run("-e", "MYSQL_ROOT_PASSWORD=foobar123", "mysql"); err != nil { @@ -180,8 +182,8 @@ func TestMysql(t *testing.T) { t.Fatalf("docker.WaitForOutput() timeout: %v", err) } - client := testutil.MakeDocker("mysql-client-test") - dir, err := testutil.PrepareFiles("mysql.sql") + client := dockerutil.MakeDocker("mysql-client-test") + dir, err := dockerutil.PrepareFiles("mysql.sql") if err != nil { t.Fatalf("PrepareFiles() failed: %v", err) } @@ -189,8 +191,8 @@ func TestMysql(t *testing.T) { // Tell mysql client to connect to the server and execute the file in verbose // mode to verify the output. args := []string{ - testutil.LinkArg(&d, "mysql"), - testutil.MountArg(dir, "/sql", testutil.ReadWrite), + dockerutil.LinkArg(&d, "mysql"), + dockerutil.MountArg(dir, "/sql", dockerutil.ReadWrite), "mysql", "mysql", "-hmysql", "-uroot", "-pfoobar123", "-v", "-e", "source /sql/mysql.sql", } @@ -212,10 +214,10 @@ func TestPythonHello(t *testing.T) { // TODO(b/136503277): Once we have more complete python runtime tests, // we can drop this one. const img = "gcr.io/gvisor-presubmit/python-hello" - if err := testutil.Pull(img); err != nil { + if err := dockerutil.Pull(img); err != nil { t.Fatalf("docker pull failed: %v", err) } - d := testutil.MakeDocker("python-hello-test") + d := dockerutil.MakeDocker("python-hello-test") if err := d.Run("-p", "8080", img); err != nil { t.Fatalf("docker run failed: %v", err) } @@ -244,10 +246,10 @@ func TestPythonHello(t *testing.T) { } func TestTomcat(t *testing.T) { - if err := testutil.Pull("tomcat:8.0"); err != nil { + if err := dockerutil.Pull("tomcat:8.0"); err != nil { t.Fatalf("docker pull failed: %v", err) } - d := testutil.MakeDocker("tomcat-test") + d := dockerutil.MakeDocker("tomcat-test") if err := d.Run("-p", "8080", "tomcat:8.0"); err != nil { t.Fatalf("docker run failed: %v", err) } @@ -276,12 +278,12 @@ func TestTomcat(t *testing.T) { } func TestRuby(t *testing.T) { - if err := testutil.Pull("ruby"); err != nil { + if err := dockerutil.Pull("ruby"); err != nil { t.Fatalf("docker pull failed: %v", err) } - d := testutil.MakeDocker("ruby-test") + d := dockerutil.MakeDocker("ruby-test") - dir, err := testutil.PrepareFiles("ruby.rb", "ruby.sh") + dir, err := dockerutil.PrepareFiles("ruby.rb", "ruby.sh") if err != nil { t.Fatalf("PrepareFiles() failed: %v", err) } @@ -289,7 +291,7 @@ func TestRuby(t *testing.T) { t.Fatalf("os.Chmod(%q, 0333) failed: %v", dir, err) } - if err := d.Run("-p", "8080", testutil.MountArg(dir, "/src", testutil.ReadOnly), "ruby", "/src/ruby.sh"); err != nil { + if err := d.Run("-p", "8080", dockerutil.MountArg(dir, "/src", dockerutil.ReadOnly), "ruby", "/src/ruby.sh"); err != nil { t.Fatalf("docker run failed: %v", err) } defer d.CleanUp() @@ -324,10 +326,10 @@ func TestRuby(t *testing.T) { } func TestStdio(t *testing.T) { - if err := testutil.Pull("alpine"); err != nil { + if err := dockerutil.Pull("alpine"); err != nil { t.Fatalf("docker pull failed: %v", err) } - d := testutil.MakeDocker("stdio-test") + d := dockerutil.MakeDocker("stdio-test") wantStdout := "hello stdout" wantStderr := "bonjour stderr" @@ -345,6 +347,7 @@ func TestStdio(t *testing.T) { } func TestMain(m *testing.M) { - testutil.EnsureSupportedDockerVersion() + dockerutil.EnsureSupportedDockerVersion() + flag.Parse() os.Exit(m.Run()) } diff --git a/runsc/test/image/latin10k.txt b/test/image/latin10k.txt index 61341e00b..61341e00b 100644 --- a/runsc/test/image/latin10k.txt +++ b/test/image/latin10k.txt diff --git a/runsc/test/image/mysql.sql b/test/image/mysql.sql index 51554b98d..51554b98d 100644 --- a/runsc/test/image/mysql.sql +++ b/test/image/mysql.sql diff --git a/runsc/test/image/ruby.rb b/test/image/ruby.rb index aced49c6d..aced49c6d 100644 --- a/runsc/test/image/ruby.rb +++ b/test/image/ruby.rb diff --git a/runsc/test/image/ruby.sh b/test/image/ruby.sh index ebe8d5b0e..ebe8d5b0e 100644 --- a/runsc/test/image/ruby.sh +++ b/test/image/ruby.sh diff --git a/runsc/test/root/BUILD b/test/root/BUILD index 500ef7b8e..f130df2c7 100644 --- a/runsc/test/root/BUILD +++ b/test/root/BUILD @@ -5,7 +5,7 @@ package(licenses = ["notice"]) go_library( name = "root", srcs = ["root.go"], - importpath = "gvisor.dev/gvisor/runsc/test/root", + importpath = "gvisor.dev/gvisor/test/root", ) go_test( @@ -23,11 +23,14 @@ go_test( "manual", "local", ], + visibility = ["//:sandbox"], deps = [ "//runsc/cgroup", + "//runsc/criutil", + "//runsc/dockerutil", "//runsc/specutils", - "//runsc/test/root/testdata", - "//runsc/test/testutil", + "//runsc/testutil", + "//test/root/testdata", "@com_github_syndtr_gocapability//capability:go_default_library", ], ) diff --git a/runsc/test/root/cgroup_test.go b/test/root/cgroup_test.go index 5392dc6e0..cc7e8583e 100644 --- a/runsc/test/root/cgroup_test.go +++ b/test/root/cgroup_test.go @@ -26,7 +26,8 @@ import ( "testing" "gvisor.dev/gvisor/runsc/cgroup" - "gvisor.dev/gvisor/runsc/test/testutil" + "gvisor.dev/gvisor/runsc/dockerutil" + "gvisor.dev/gvisor/runsc/testutil" ) func verifyPid(pid int, path string) error { @@ -56,10 +57,10 @@ func verifyPid(pid int, path string) error { // TestCgroup sets cgroup options and checks that cgroup was properly configured. func TestCgroup(t *testing.T) { - if err := testutil.Pull("alpine"); err != nil { + if err := dockerutil.Pull("alpine"); err != nil { t.Fatal("docker pull failed:", err) } - d := testutil.MakeDocker("cgroup-test") + d := dockerutil.MakeDocker("cgroup-test") attrs := []struct { arg string @@ -197,10 +198,10 @@ func TestCgroup(t *testing.T) { } func TestCgroupParent(t *testing.T) { - if err := testutil.Pull("alpine"); err != nil { + if err := dockerutil.Pull("alpine"); err != nil { t.Fatal("docker pull failed:", err) } - d := testutil.MakeDocker("cgroup-test") + d := dockerutil.MakeDocker("cgroup-test") parent := testutil.RandomName("runsc") if err := d.Run("--cgroup-parent", parent, "alpine", "sleep", "10000"); err != nil { diff --git a/runsc/test/root/chroot_test.go b/test/root/chroot_test.go index d0f236580..f47f8e2c2 100644 --- a/runsc/test/root/chroot_test.go +++ b/test/root/chroot_test.go @@ -12,15 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -// Package root is used for tests that requires sysadmin privileges run. First, -// follow the setup instruction in runsc/test/README.md. To run these tests: -// -// bazel build //runsc/test/root:root_test -// root_test=$(find -L ./bazel-bin/ -executable -type f -name root_test | grep __main__) -// sudo RUNSC_RUNTIME=runsc-test ${root_test} +// Package root is used for tests that requires sysadmin privileges run. package root import ( + "flag" "fmt" "io/ioutil" "os" @@ -31,14 +27,14 @@ import ( "testing" "github.com/syndtr/gocapability/capability" + "gvisor.dev/gvisor/runsc/dockerutil" "gvisor.dev/gvisor/runsc/specutils" - "gvisor.dev/gvisor/runsc/test/testutil" ) // TestChroot verifies that the sandbox is chroot'd and that mounts are cleaned // up after the sandbox is destroyed. func TestChroot(t *testing.T) { - d := testutil.MakeDocker("chroot-test") + d := dockerutil.MakeDocker("chroot-test") if err := d.Run("alpine", "sleep", "10000"); err != nil { t.Fatalf("docker run failed: %v", err) } @@ -84,7 +80,7 @@ func TestChroot(t *testing.T) { } func TestChrootGofer(t *testing.T) { - d := testutil.MakeDocker("chroot-test") + d := dockerutil.MakeDocker("chroot-test") if err := d.Run("alpine", "sleep", "10000"); err != nil { t.Fatalf("docker run failed: %v", err) } @@ -150,12 +146,13 @@ func TestChrootGofer(t *testing.T) { } func TestMain(m *testing.M) { - testutil.EnsureSupportedDockerVersion() + dockerutil.EnsureSupportedDockerVersion() if !specutils.HasCapabilities(capability.CAP_SYS_ADMIN, capability.CAP_DAC_OVERRIDE) { fmt.Println("Test requires sysadmin privileges to run. Try again with sudo.") os.Exit(1) } + flag.Parse() os.Exit(m.Run()) } diff --git a/runsc/test/root/crictl_test.go b/test/root/crictl_test.go index 515ae2df1..d597664f5 100644 --- a/runsc/test/root/crictl_test.go +++ b/test/root/crictl_test.go @@ -29,14 +29,17 @@ import ( "testing" "time" + "gvisor.dev/gvisor/runsc/criutil" + "gvisor.dev/gvisor/runsc/dockerutil" "gvisor.dev/gvisor/runsc/specutils" - "gvisor.dev/gvisor/runsc/test/root/testdata" - "gvisor.dev/gvisor/runsc/test/testutil" + "gvisor.dev/gvisor/runsc/testutil" + "gvisor.dev/gvisor/test/root/testdata" ) // Tests for crictl have to be run as root (rather than in a user namespace) // because crictl creates named network namespaces in /var/run/netns/. +// TestCrictlSanity refers to b/112433158. func TestCrictlSanity(t *testing.T) { // Setup containerd and crictl. crictl, cleanup, err := setup(t) @@ -60,6 +63,7 @@ func TestCrictlSanity(t *testing.T) { } } +// TestMountPaths refers to b/117635704. func TestMountPaths(t *testing.T) { // Setup containerd and crictl. crictl, cleanup, err := setup(t) @@ -83,6 +87,7 @@ func TestMountPaths(t *testing.T) { } } +// TestMountPaths refers to b/118728671. func TestMountOverSymlinks(t *testing.T) { // Setup containerd and crictl. crictl, cleanup, err := setup(t) @@ -125,7 +130,7 @@ func TestMountOverSymlinks(t *testing.T) { // * Creates directories and a socket for containerd to utilize. // * Runs containerd and waits for it to reach a "ready" state for testing. // * Returns a cleanup function that should be called at the end of the test. -func setup(t *testing.T) (*testutil.Crictl, func(), error) { +func setup(t *testing.T) (*criutil.Crictl, func(), error) { var cleanups []func() cleanupFunc := func() { for i := len(cleanups) - 1; i >= 0; i-- { @@ -149,12 +154,19 @@ func setup(t *testing.T) (*testutil.Crictl, func(), error) { cleanups = append(cleanups, func() { os.RemoveAll(containerdState) }) sockAddr := filepath.Join(testutil.TmpDir(), "containerd-test.sock") - // Start containerd. - config, err := testutil.WriteTmpFile("containerd-config", testdata.ContainerdConfig(getRunsc())) + // We rewrite a configuration. This is based on the current docker + // configuration for the runtime under test. + runtime, err := dockerutil.RuntimePath() + if err != nil { + t.Fatalf("error discovering runtime path: %v", err) + } + config, err := testutil.WriteTmpFile("containerd-config", testdata.ContainerdConfig(runtime)) if err != nil { t.Fatalf("failed to write containerd config") } cleanups = append(cleanups, func() { os.RemoveAll(config) }) + + // Start containerd. containerd := exec.Command(getContainerd(), "--config", config, "--log-level", "debug", @@ -191,11 +203,11 @@ func setup(t *testing.T) (*testutil.Crictl, func(), error) { }) cleanup.Release() - return testutil.NewCrictl(20*time.Second, sockAddr), cleanupFunc, nil + return criutil.NewCrictl(20*time.Second, sockAddr), cleanupFunc, nil } // httpGet GETs the contents of a file served from a pod on port 80. -func httpGet(crictl *testutil.Crictl, podID, filePath string) error { +func httpGet(crictl *criutil.Crictl, podID, filePath string) error { // Get the IP of the httpd server. ip, err := crictl.PodIP(podID) if err != nil { @@ -222,21 +234,9 @@ func httpGet(crictl *testutil.Crictl, podID, filePath string) error { } func getContainerd() string { - // Bazel doesn't pass PATH through, assume the location of containerd - // unless specified by environment variable. - c := os.Getenv("CONTAINERD_PATH") - if c == "" { + // Use the local path if it exists, otherwise, use the system one. + if _, err := os.Stat("/usr/local/bin/containerd"); err == nil { return "/usr/local/bin/containerd" } - return c -} - -func getRunsc() string { - // Bazel doesn't pass PATH through, assume the location of runsc unless - // specified by environment variable. - c := os.Getenv("RUNSC_EXEC") - if c == "" { - return "/tmp/runsc-test/runsc" - } - return c + return "/usr/bin/containerd" } diff --git a/runsc/test/root/root.go b/test/root/root.go index 349c752cc..349c752cc 100644 --- a/runsc/test/root/root.go +++ b/test/root/root.go diff --git a/runsc/test/root/testdata/BUILD b/test/root/testdata/BUILD index 80dc5f214..14c19ef1e 100644 --- a/runsc/test/root/testdata/BUILD +++ b/test/root/testdata/BUILD @@ -11,7 +11,7 @@ go_library( "httpd_mount_paths.go", "sandbox.go", ], - importpath = "gvisor.dev/gvisor/runsc/test/root/testdata", + importpath = "gvisor.dev/gvisor/test/root/testdata", visibility = [ "//visibility:public", ], diff --git a/runsc/test/root/testdata/busybox.go b/test/root/testdata/busybox.go index e4dbd2843..e4dbd2843 100644 --- a/runsc/test/root/testdata/busybox.go +++ b/test/root/testdata/busybox.go diff --git a/runsc/test/root/testdata/containerd_config.go b/test/root/testdata/containerd_config.go index e12f1ec88..e12f1ec88 100644 --- a/runsc/test/root/testdata/containerd_config.go +++ b/test/root/testdata/containerd_config.go diff --git a/runsc/test/root/testdata/httpd.go b/test/root/testdata/httpd.go index 45d5e33d4..45d5e33d4 100644 --- a/runsc/test/root/testdata/httpd.go +++ b/test/root/testdata/httpd.go diff --git a/runsc/test/root/testdata/httpd_mount_paths.go b/test/root/testdata/httpd_mount_paths.go index ac3f4446a..ac3f4446a 100644 --- a/runsc/test/root/testdata/httpd_mount_paths.go +++ b/test/root/testdata/httpd_mount_paths.go diff --git a/runsc/test/root/testdata/sandbox.go b/test/root/testdata/sandbox.go index 0db210370..0db210370 100644 --- a/runsc/test/root/testdata/sandbox.go +++ b/test/root/testdata/sandbox.go diff --git a/test/runtimes/BUILD b/test/runtimes/BUILD index e85804a83..5616a8b7b 100644 --- a/test/runtimes/BUILD +++ b/test/runtimes/BUILD @@ -1,7 +1,7 @@ # These packages are used to run language runtime tests inside gVisor sandboxes. load("@io_bazel_rules_go//go:def.bzl", "go_library") -load("//runsc/test:build_defs.bzl", "runtime_test") +load("//test/runtimes:build_defs.bzl", "runtime_test") package(licenses = ["notice"]) @@ -21,5 +21,5 @@ runtime_test( "manual", "local", ], - deps = ["//runsc/test/testutil"], + deps = ["//runsc/testutil"], ) diff --git a/runsc/test/build_defs.bzl b/test/runtimes/build_defs.bzl index ac28cc037..ac28cc037 100644 --- a/runsc/test/build_defs.bzl +++ b/test/runtimes/build_defs.bzl diff --git a/test/runtimes/common/BUILD b/test/runtimes/common/BUILD index 1b39606b8..b4740bb97 100644 --- a/test/runtimes/common/BUILD +++ b/test/runtimes/common/BUILD @@ -15,6 +15,6 @@ go_test( srcs = ["common_test.go"], deps = [ ":common", - "//runsc/test/testutil", + "//runsc/testutil", ], ) diff --git a/test/runtimes/common/common_test.go b/test/runtimes/common/common_test.go index 4fb1e482a..65875b41b 100644 --- a/test/runtimes/common/common_test.go +++ b/test/runtimes/common/common_test.go @@ -23,7 +23,7 @@ import ( "strings" "testing" - "gvisor.dev/gvisor/runsc/test/testutil" + "gvisor.dev/gvisor/runsc/testutil" "gvisor.dev/gvisor/test/runtimes/common" ) diff --git a/test/runtimes/runtimes_test.go b/test/runtimes/runtimes_test.go index 9421021a1..0ff5dda02 100644 --- a/test/runtimes/runtimes_test.go +++ b/test/runtimes/runtimes_test.go @@ -19,7 +19,7 @@ import ( "testing" "time" - "gvisor.dev/gvisor/runsc/test/testutil" + "gvisor.dev/gvisor/runsc/testutil" ) // Wait time for each test to run. diff --git a/test/syscalls/BUILD b/test/syscalls/BUILD index a8a2e75d3..58eb1154a 100644 --- a/test/syscalls/BUILD +++ b/test/syscalls/BUILD @@ -693,6 +693,7 @@ syscall_test(test = "//test/syscalls/linux:proc_net_udp_test") go_binary( name = "syscall_test_runner", + testonly = 1, srcs = ["syscall_test_runner.go"], data = [ "//runsc", @@ -700,7 +701,7 @@ go_binary( deps = [ "//pkg/log", "//runsc/specutils", - "//runsc/test/testutil", + "//runsc/testutil", "//test/syscalls/gtest", "@com_github_opencontainers_runtime-spec//specs-go:go_default_library", "@org_golang_x_sys//unix:go_default_library", diff --git a/test/syscalls/build_defs.bzl b/test/syscalls/build_defs.bzl index 60df47798..e94ef5602 100644 --- a/test/syscalls/build_defs.bzl +++ b/test/syscalls/build_defs.bzl @@ -94,6 +94,7 @@ def _syscall_test( # more stable. if platform == "kvm": tags += ["manual"] + tags += ["requires-kvm"] args = [ # Arguments are passed directly to syscall_test_runner binary. diff --git a/test/syscalls/syscall_test_runner.go b/test/syscalls/syscall_test_runner.go index 32408f021..e900f8abc 100644 --- a/test/syscalls/syscall_test_runner.go +++ b/test/syscalls/syscall_test_runner.go @@ -35,7 +35,7 @@ import ( "golang.org/x/sys/unix" "gvisor.dev/gvisor/pkg/log" "gvisor.dev/gvisor/runsc/specutils" - "gvisor.dev/gvisor/runsc/test/testutil" + "gvisor.dev/gvisor/runsc/testutil" "gvisor.dev/gvisor/test/syscalls/gtest" ) diff --git a/tools/make_repository.sh b/tools/make_repository.sh new file mode 100755 index 000000000..bf9c50d74 --- /dev/null +++ b/tools/make_repository.sh @@ -0,0 +1,69 @@ +#!/bin/bash + +# Copyright 2018 The gVisor 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. + +# Parse arguments. We require more than two arguments, which are the private +# keyring, the e-mail associated with the signer, and the list of packages. +if [ "$#" -le 2 ]; then + echo "usage: $0 <private-key> <signer-email> <packages...>" + exit 1 +fi +declare -r private_key=$(readlink -e "$1") +declare -r signer="$2" +shift; shift + +# Verbose from this point. +set -xeo pipefail + +# Create a temporary working directory. We don't remove this, as we ultimately +# print this result and allow the caller to copy wherever they would like. +declare -r tmpdir=$(mktemp -d /tmp/repoXXXXXX) + +# Create a temporary keyring, and ensure it is cleaned up. +declare -r keyring=$(mktemp /tmp/keyringXXXXXX.gpg) +cleanup() { + rm -f "${keyring}" +} +trap cleanup EXIT +gpg --no-default-keyring --keyring "${keyring}" --import "${private_key}" + +# Export the public key from the keyring. +gpg --no-default-keyring --keyring "${keyring}" --armor --export "${signer}" > "${tmpdir}"/keyFile + +# Copy the packages, and ensure permissions are correct. +cp -a "$@" "${tmpdir}" && chmod 0644 "${tmpdir}"/* + +# Ensure there are no symlinks hanging around; these may be remnants of the +# build process. They may be useful for other things, but we are going to build +# an index of the actual packages here. +find "${tmpdir}" -type l -exec rm -f {} \; + +# Sign all packages. +for file in "${tmpdir}"/*.deb; do + dpkg-sig -g "--no-default-keyring --keyring ${keyring}" --sign builder "${file}" +done + +# Build the package list. +(cd "${tmpdir}" && apt-ftparchive packages . | gzip > Packages.gz) + +# Build the release list. +(cd "${tmpdir}" && apt-ftparchive release . > Release) + +# Sign the release. +(cd "${tmpdir}" && gpg --no-default-keyring --keyring "${keyring}" --clearsign -o InRelease Release) +(cd "${tmpdir}" && gpg --no-default-keyring --keyring "${keyring}" -abs -o Release.gpg Release) + +# Show the results. +echo "${tmpdir}" diff --git a/tools/run_build.sh b/tools/run_build.sh deleted file mode 100755 index 7f6ada480..000000000 --- a/tools/run_build.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/bash - -# Copyright 2018 The gVisor 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. - -# Fail on any error. -set -e -# Display commands to stderr. -set -x - -# Install the latest version of Bazel and log the version. -(which use_bazel.sh && use_bazel.sh latest) || which bazel -bazel version - -# Switch into the workspace. -if [[ -v KOKORO_GIT_COMMIT ]] && [[ -d git/repo ]]; then - cd git/repo -elif [[ -v KOKORO_GIT_COMMIT ]] && [[ -d github/repo ]]; then - cd github/repo -fi - -# Build runsc. -bazel build -c opt --strip=never //runsc - -# Move the runsc binary into "latest" directory, and also a directory with the -# current date. -if [[ -v KOKORO_ARTIFACTS_DIR ]]; then - latest_dir="${KOKORO_ARTIFACTS_DIR}"/latest - today_dir="${KOKORO_ARTIFACTS_DIR}"/"$(date -Idate)" - runsc="bazel-bin/runsc/linux_amd64_pure/runsc" - - mkdir -p "${latest_dir}" "${today_dir}" - cp "${runsc}" "${latest_dir}" - cp "${runsc}" "${today_dir}" - - sha512sum "${latest_dir}"/runsc | awk '{print $1 " runsc"}' > "${latest_dir}"/runsc.sha512 - cp "${latest_dir}"/runsc.sha512 "${today_dir}"/runsc.sha512 -fi diff --git a/tools/run_tests.sh b/tools/run_tests.sh deleted file mode 100755 index 6fe80a36b..000000000 --- a/tools/run_tests.sh +++ /dev/null @@ -1,304 +0,0 @@ -#!/bin/bash - -# Copyright 2018 The gVisor 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. - -# Fail on any error. Treat unset variables as error. Print commands as executed. -set -eux - -################### -# GLOBAL ENV VARS # -################### - -if [[ -v KOKORO_GIT_COMMIT ]] && [[ -d git/repo ]]; then - readonly WORKSPACE_DIR="${PWD}/git/repo" -elif [[ -v KOKORO_GIT_COMMIT ]] && [[ -d github/repo ]]; then - readonly WORKSPACE_DIR="${PWD}/github/repo" -else - readonly WORKSPACE_DIR="${PWD}" -fi - -# Used to configure RBE. -readonly CLOUD_PROJECT_ID="gvisor-rbe" -readonly RBE_PROJECT_ID="projects/${CLOUD_PROJECT_ID}/instances/default_instance" - -# Random runtime name to avoid collisions. -readonly RUNTIME="runsc_test_$((RANDOM))" - -# Packages that will be built and tested. -readonly BUILD_PACKAGES=("//...") -readonly TEST_PACKAGES=("//pkg/..." "//runsc/..." "//tools/...") - -####################### -# BAZEL CONFIGURATION # -####################### - -# Install the latest version of Bazel and log the version. -(which use_bazel.sh && use_bazel.sh 0.28.0) || which bazel -bazel version - -# Load the kvm module. -sudo -n -E modprobe kvm - -# General Bazel build/test flags. -BAZEL_BUILD_FLAGS=( - "--show_timestamps" - "--test_output=errors" - "--keep_going" - "--verbose_failures=true" -) - -# Bazel build/test for RBE, a super-set of BAZEL_BUILD_FLAGS. -BAZEL_BUILD_RBE_FLAGS=( - "${BAZEL_BUILD_FLAGS[@]}" - "--config=remote" - "--project_id=${CLOUD_PROJECT_ID}" - "--remote_instance_name=${RBE_PROJECT_ID}" -) -if [[ -v KOKORO_BAZEL_AUTH_CREDENTIAL ]]; then - BAZEL_BUILD_RBE_FLAGS=( - "${BAZEL_BUILD_RBE_FLAGS[@]}" - "--auth_credentials=${KOKORO_BAZEL_AUTH_CREDENTIAL}" - ) -fi - -#################### -# Helper Functions # -#################### - -sanity_checks() { - cd ${WORKSPACE_DIR} - bazel run //:gazelle -- update-repos -from_file=go.mod - git diff --exit-code WORKSPACE -} - -build_everything() { - FLAVOR="${1}" - - cd ${WORKSPACE_DIR} - bazel build \ - -c "${FLAVOR}" "${BAZEL_BUILD_RBE_FLAGS[@]}" \ - "${BUILD_PACKAGES[@]}" -} - -build_runsc_debian() { - cd ${WORKSPACE_DIR} - - # TODO(b/135475885): pkg_deb is incompatible with Python3. - # https://github.com/bazelbuild/bazel/issues/8443 - bazel build --host_force_python=py2 runsc:runsc-debian -} - -# Run simple tests runs the tests that require no special setup or -# configuration. -run_simple_tests() { - cd ${WORKSPACE_DIR} - bazel test \ - "${BAZEL_BUILD_FLAGS[@]}" \ - "${TEST_PACKAGES[@]}" -} - -install_runtime() { - cd ${WORKSPACE_DIR} - sudo -n ${WORKSPACE_DIR}/runsc/test/install.sh --runtime ${RUNTIME} -} - -install_helper() { - PACKAGE="${1}" - TAG="${2}" - GOPATH="${3}" - - # Clone the repository. - mkdir -p "${GOPATH}"/src/$(dirname "${PACKAGE}") && \ - git clone https://"${PACKAGE}" "${GOPATH}"/src/"${PACKAGE}" - - # Checkout and build the repository. - (cd "${GOPATH}"/src/"${PACKAGE}" && \ - git checkout "${TAG}" && \ - GOPATH="${GOPATH}" make && \ - sudo -n -E env GOPATH="${GOPATH}" make install) -} - -# Install dependencies for the crictl tests. -install_crictl_test_deps() { - sudo -n -E apt-get update - sudo -n -E apt-get install -y btrfs-tools libseccomp-dev - - # Install containerd & cri-tools. - GOPATH=$(mktemp -d --tmpdir gopathXXXXX) - install_helper github.com/containerd/containerd v1.2.2 "${GOPATH}" - install_helper github.com/kubernetes-sigs/cri-tools v1.11.0 "${GOPATH}" - - # Install gvisor-containerd-shim. - local latest=/tmp/gvisor-containerd-shim-latest - local shim_path=/tmp/gvisor-containerd-shim - wget --no-verbose https://storage.googleapis.com/cri-containerd-staging/gvisor-containerd-shim/latest -O ${latest} - wget --no-verbose https://storage.googleapis.com/cri-containerd-staging/gvisor-containerd-shim/gvisor-containerd-shim-$(cat ${latest}) -O ${shim_path} - chmod +x ${shim_path} - sudo -n -E mv ${shim_path} /usr/local/bin - - # Configure containerd-shim. - local shim_config_path=/etc/containerd - local shim_config_tmp_path=/tmp/gvisor-containerd-shim.toml - sudo -n -E mkdir -p ${shim_config_path} - cat > ${shim_config_tmp_path} <<-EOF - runc_shim = "/usr/local/bin/containerd-shim" - - [runsc_config] - debug = "true" - debug-log = "/tmp/runsc-logs/" - strace = "true" - file-access = "shared" -EOF - sudo mv ${shim_config_tmp_path} ${shim_config_path} - - # Configure CNI. - (cd "${GOPATH}" && sudo -n -E env PATH="${PATH}" GOPATH="${GOPATH}" \ - src/github.com/containerd/containerd/script/setup/install-cni) -} - -# Run the tests that require docker. -run_docker_tests() { - cd ${WORKSPACE_DIR} - - # Run tests with a default runtime (runc). - bazel test \ - "${BAZEL_BUILD_FLAGS[@]}" \ - --test_env=RUNSC_RUNTIME="" \ - //runsc/test/image:image_test - - # These names are used to exclude tests not supported in certain - # configuration, e.g. save/restore not supported with hostnet. - # Run runsc tests with docker that are tagged manual. - # - # The --nocache_test_results option is used here to eliminate cached results - # from the previous run for the runc runtime. - bazel test \ - "${BAZEL_BUILD_FLAGS[@]}" \ - --test_env=RUNSC_RUNTIME="${RUNTIME}" \ - --nocache_test_results \ - //runsc/test/integration:integration_test \ - //runsc/test/integration:integration_test_hostnet \ - //runsc/test/integration:integration_test_overlay \ - //runsc/test/integration:integration_test_kvm \ - //runsc/test/image:image_test \ - //runsc/test/image:image_test_overlay \ - //runsc/test/image:image_test_hostnet \ - //runsc/test/image:image_test_kvm -} - -# Run the tests that require root. -run_root_tests() { - cd ${WORKSPACE_DIR} - bazel build //runsc/test/root:root_test - local root_test=$(find -L ./bazel-bin/ -executable -type f -name root_test | grep __main__) - if [[ ! -f "${root_test}" ]]; then - echo "root_test executable not found" - exit 1 - fi - sudo -n -E RUNSC_RUNTIME="${RUNTIME}" RUNSC_EXEC=/tmp/"${RUNTIME}"/runsc ${root_test} -} - -# Run syscall unit tests. -run_syscall_tests() { - cd ${WORKSPACE_DIR} - bazel test "${BAZEL_BUILD_RBE_FLAGS[@]}" \ - --test_tag_filters=runsc_ptrace //test/syscalls/... -} - -run_runsc_do_tests() { - local runsc=$(find bazel-bin/runsc -type f -executable -name "runsc" | head -n1) - - # run runsc do without root privileges. - ${runsc} --rootless do true - ${runsc} --rootless --network=none do true - - # run runsc do with root privileges. - sudo -n -E ${runsc} do true -} - -# Find and rename all test xml and log files so that Sponge can pick them up. -# XML files must be named sponge_log.xml, and log files must be named -# sponge_log.log. We move all such files into KOKORO_ARTIFACTS_DIR, in a -# subdirectory named with the test name. -upload_test_artifacts() { - # Skip if no kokoro directory. - [[ -v KOKORO_ARTIFACTS_DIR ]] || return - - cd ${WORKSPACE_DIR} - find -L "bazel-testlogs" -name "test.xml" -o -name "test.log" -o -name "outputs.zip" | - tar --create --files-from - --transform 's/test\./sponge_log./' | - tar --extract --directory ${KOKORO_ARTIFACTS_DIR} - if [[ -d "/tmp/${RUNTIME}/logs" ]]; then - tar --create --gzip "--file=${KOKORO_ARTIFACTS_DIR}/runsc-logs.tar.gz" -C /tmp/ ${RUNTIME}/logs - fi -} - -# Finish runs in the event of an error, uploading all artifacts. -finish() { - # Grab the last exit code, we will return it. - local exit_code=${?} - upload_test_artifacts - exit ${exit_code} -} - -# Run bazel in a docker container -build_in_docker() { - cd ${WORKSPACE_DIR} - bazel clean - bazel shutdown - make - make runsc - make bazel-shutdown -} - -######## -# MAIN # -######## - -main() { - # Register finish to run at exit. - trap finish EXIT - - # Build and run the simple tests. - sanity_checks - build_everything opt - run_simple_tests - - # So far so good. Install more deps and run the integration tests. - install_runtime - install_crictl_test_deps - run_docker_tests - run_root_tests - - run_syscall_tests - run_runsc_do_tests - - build_runsc_debian - - # Build other flavors too. - build_everything dbg - - # We need to upload all the existing test logs and artifacts before shutting - # down and cleaning bazel, otherwise all test information is lost. After this - # point, we don't expect any logs or artifacts. - upload_test_artifacts - trap - EXIT - - # Run docker build tests. - build_in_docker -} - -# Kick it off. -main |