diff options
-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 |