summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/issue_reviver.yml4
-rw-r--r--Makefile10
-rw-r--r--WORKSPACE631
-rw-r--r--benchmarks/harness/BUILD1
-rw-r--r--g3doc/user_guide/runtimeclass.md10
-rw-r--r--go.mod76
-rw-r--r--go.sum435
-rw-r--r--images/benchmarks/absl/Dockerfile21
-rw-r--r--images/benchmarks/iperf/Dockerfile8
-rw-r--r--pkg/sentry/fsimpl/ext/BUILD4
-rw-r--r--pkg/sentry/fsimpl/gofer/gofer.go24
-rw-r--r--pkg/sentry/fsimpl/gofer/regular_file.go4
-rw-r--r--pkg/sentry/fsimpl/kernfs/BUILD2
-rw-r--r--pkg/sentry/fsimpl/sys/BUILD2
-rw-r--r--pkg/sentry/fsimpl/testutil/BUILD2
-rw-r--r--pkg/sentry/kernel/timekeeper.go3
-rw-r--r--pkg/sentry/platform/kvm/machine_arm64_unsafe.go13
-rw-r--r--pkg/sentry/platform/ring0/entry_arm64.s13
-rw-r--r--pkg/sentry/socket/netstack/netstack.go6
-rw-r--r--pkg/sentry/time/parameters.go12
-rw-r--r--pkg/sentry/vfs/inotify.go6
-rw-r--r--pkg/shim/runsc/BUILD2
-rw-r--r--pkg/shim/runsc/runsc.go2
-rw-r--r--pkg/shim/runsc/utils.go2
-rw-r--r--pkg/shim/v1/proc/BUILD5
-rw-r--r--pkg/shim/v1/proc/deleted_state.go12
-rw-r--r--pkg/shim/v1/proc/exec.go12
-rw-r--r--pkg/shim/v1/proc/init.go26
-rw-r--r--pkg/shim/v1/proc/init_state.go18
-rw-r--r--pkg/shim/v1/proc/io.go8
-rw-r--r--pkg/shim/v1/proc/types.go7
-rw-r--r--pkg/shim/v1/shim/BUILD6
-rw-r--r--pkg/shim/v1/shim/api.go28
-rw-r--r--pkg/shim/v1/shim/platform.go6
-rw-r--r--pkg/shim/v1/shim/service.go96
-rw-r--r--pkg/shim/v1/utils/BUILD5
-rw-r--r--pkg/shim/v1/utils/annotations.go25
-rw-r--r--pkg/shim/v1/utils/utils.go7
-rw-r--r--pkg/shim/v1/utils/volumes.go4
-rw-r--r--pkg/shim/v1/utils/volumes_test.go45
-rw-r--r--pkg/shim/v2/BUILD8
-rw-r--r--pkg/shim/v2/api.go22
-rw-r--r--pkg/shim/v2/epoll.go11
-rw-r--r--pkg/shim/v2/runtimeoptions/BUILD20
-rw-r--r--pkg/shim/v2/runtimeoptions/runtimeoptions.go27
-rw-r--r--pkg/shim/v2/runtimeoptions/runtimeoptions.proto25
-rw-r--r--pkg/shim/v2/service.go102
-rw-r--r--pkg/shim/v2/service_linux.go6
-rw-r--r--pkg/sleep/BUILD1
-rw-r--r--pkg/sleep/sleep_test.go20
-rw-r--r--pkg/sleep/sleep_unsafe.go7
-rw-r--r--pkg/sync/BUILD1
-rw-r--r--pkg/sync/nocopy.go28
-rw-r--r--pkg/tcpip/header/BUILD4
-rw-r--r--pkg/tcpip/link/fdbased/endpoint_test.go73
-rw-r--r--pkg/tcpip/link/fdbased/packet_dispatchers.go2
-rw-r--r--pkg/tcpip/network/ipv4/BUILD2
-rw-r--r--pkg/tcpip/network/ipv6/BUILD2
-rw-r--r--pkg/tcpip/stack/BUILD16
-rw-r--r--pkg/tcpip/stack/conntrack.go277
-rw-r--r--pkg/tcpip/stack/iptables.go42
-rw-r--r--pkg/tcpip/stack/iptables_state.go40
-rw-r--r--pkg/tcpip/stack/iptables_types.go11
-rw-r--r--pkg/tcpip/stack/packet_buffer.go14
-rw-r--r--pkg/tcpip/stack/stack.go1
-rw-r--r--pkg/tcpip/tcpip.go10
-rw-r--r--pkg/tcpip/timer.go21
-rw-r--r--pkg/tcpip/transport/icmp/endpoint.go4
-rw-r--r--pkg/tcpip/transport/packet/endpoint.go8
-rw-r--r--pkg/tcpip/transport/raw/endpoint.go8
-rw-r--r--pkg/tcpip/transport/tcp/endpoint.go3
-rw-r--r--pkg/tcpip/transport/tcpconntrack/tcp_conntrack.go5
-rw-r--r--pkg/tcpip/transport/udp/endpoint.go14
-rw-r--r--pkg/tcpip/transport/udp/udp_test.go104
-rw-r--r--pkg/test/criutil/criutil.go3
-rw-r--r--pkg/test/dockerutil/dockerutil.go5
-rw-r--r--pkg/test/testutil/BUILD2
-rw-r--r--runsc/boot/BUILD4
-rw-r--r--runsc/cgroup/BUILD4
-rw-r--r--runsc/cmd/BUILD8
-rw-r--r--runsc/container/BUILD4
-rw-r--r--runsc/sandbox/BUILD2
-rw-r--r--runsc/specutils/BUILD4
-rwxr-xr-xscripts/benchmark.sh33
-rwxr-xr-xscripts/common.sh27
-rwxr-xr-xscripts/common_build.sh2
-rwxr-xr-xscripts/packetdrill_tests.sh2
-rwxr-xr-xscripts/packetimpact_tests.sh2
-rwxr-xr-xscripts/root_tests.sh11
-rwxr-xr-xscripts/runtime_tests.sh2
-rw-r--r--shim/v1/BUILD10
-rw-r--r--shim/v1/README.md14
-rw-r--r--shim/v1/api.go24
-rw-r--r--shim/v1/main.go38
-rw-r--r--shim/v2/BUILD7
-rw-r--r--shim/v2/README.md15
-rw-r--r--shim/v2/main.go4
-rw-r--r--shim/v2/runtime-handler-shim-v2-quickstart.md59
-rw-r--r--test/benchmarks/README.md118
-rw-r--r--test/benchmarks/fs/BUILD24
-rw-r--r--test/benchmarks/fs/bazel_test.go103
-rw-r--r--test/benchmarks/fs/fs.go16
-rw-r--r--test/benchmarks/harness/BUILD18
-rw-r--r--test/benchmarks/harness/harness.go38
-rw-r--r--test/benchmarks/harness/machine.go64
-rw-r--r--test/benchmarks/harness/util.go38
-rw-r--r--test/benchmarks/network/BUILD25
-rw-r--r--test/benchmarks/network/iperf_test.go151
-rw-r--r--test/benchmarks/network/network.go16
-rw-r--r--test/packetimpact/runner/packetimpact_test.go10
-rw-r--r--test/packetimpact/testbench/BUILD4
-rw-r--r--test/packetimpact/testbench/testbench.go25
-rw-r--r--test/packetimpact/tests/BUILD4
-rw-r--r--test/packetimpact/tests/udp_recv_mcast_bcast_test.go (renamed from test/packetimpact/tests/udp_recv_multicast_test.go)33
-rw-r--r--test/root/BUILD2
-rw-r--r--test/runner/BUILD2
-rw-r--r--test/runtimes/BUILD5
-rw-r--r--test/runtimes/exclude_nodejs12.4.0.csv3
-rw-r--r--test/runtimes/exclude_php7.3.6.csv6
-rw-r--r--test/runtimes/proctor/go.go29
-rw-r--r--test/runtimes/proctor/java.go18
-rw-r--r--test/runtimes/proctor/nodejs.go8
-rw-r--r--test/runtimes/proctor/php.go9
-rw-r--r--test/runtimes/proctor/proctor.go28
-rw-r--r--test/runtimes/proctor/python.go8
-rw-r--r--test/runtimes/runner/BUILD1
-rw-r--r--test/runtimes/runner/exclude_test.go2
-rw-r--r--test/runtimes/runner/main.go38
-rw-r--r--test/syscalls/linux/BUILD3
-rw-r--r--test/syscalls/linux/packet_socket_raw.cc34
-rw-r--r--test/syscalls/linux/raw_socket.cc37
-rw-r--r--test/syscalls/linux/tcp_socket.cc60
-rw-r--r--test/syscalls/linux/udp_socket_test_cases.cc54
-rw-r--r--test/util/test_util.h19
-rwxr-xr-xtools/go.sh29
-rw-r--r--tools/go_generics/defs.bzl41
-rw-r--r--tools/go_marshal/test/BUILD2
-rw-r--r--tools/installers/BUILD22
-rwxr-xr-xtools/installers/head.sh10
-rwxr-xr-xtools/installers/shim.sh25
-rw-r--r--tools/issue_reviver/github/BUILD3
-rw-r--r--tools/nogo/build.go4
-rw-r--r--tools/nogo/nogo.go19
-rwxr-xr-xtools/vm/ubuntu1604/30_docker.sh3
-rw-r--r--website/BUILD3
145 files changed, 2953 insertions, 1089 deletions
diff --git a/.github/workflows/issue_reviver.yml b/.github/workflows/issue_reviver.yml
index 5e0254111..e68e15270 100644
--- a/.github/workflows/issue_reviver.yml
+++ b/.github/workflows/issue_reviver.yml
@@ -4,11 +4,13 @@ on:
- cron: '0 0 * * *'
jobs:
- label:
+ issue_reviver:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
+ if: github.repository == "google/gvisor"
- run: make run TARGETS="//tools/issue_reviver"
+ if: github.repository == "google/gvisor"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_REPOSITORY: ${{ github.repository }}
diff --git a/Makefile b/Makefile
index 58648f5d2..599cb350f 100644
--- a/Makefile
+++ b/Makefile
@@ -121,10 +121,10 @@ tests: ## Runs all local ptrace system call tests.
@$(MAKE) test OPTIONS="--test_tag_filters runsc_ptrace test/syscalls/..."
.PHONY: tests
-containerd-test-%: ## Runs a local containerd test.
-containerd-test-%: load-basic_alpine load-basic_python load-basic_busybox load-basic_resolv load-basic_httpd
-containerd-test-%: install-test-runtime
+# Specific containerd version tests.
+containerd-test-%: load-basic_alpine load-basic_python load-basic_busybox load-basic_resolv load-basic_httpd install-test-runtime
@CONTAINERD_VERSION=$* $(MAKE) sudo TARGETS="tools/installers:containerd"
+ @$(MAKE) sudo TARGETS="tools/installers:shim"
@$(MAKE) sudo TARGETS="test/root:root_test" ARGS="-test.v"
# Note that we can't run containerd-test-1.1.8 tests here.
@@ -250,8 +250,6 @@ dev: ## Installs a set of local runtimes. Requires sudo.
refresh: ## Refreshes the runtime binary (for development only). Must have called 'dev' or 'test-install' first.
@mkdir -p "$(RUNTIME_DIR)"
@$(MAKE) copy TARGETS=runsc DESTINATION="$(RUNTIME_BIN)"
- @$(MAKE) copy TARGETS=shim/v1:gvisor-containerd-shim DESTINATION="$(RUNTIME_DIR)"
- @$(MAKE) copy TARGETS=shim/v2:containerd-shim-runsc-v1 DESTINATION="$(RUNTIME_DIR)"
.PHONY: install
install-test-runtime: ## Installs the runtime for testing. Requires sudo.
@@ -259,7 +257,7 @@ install-test-runtime: ## Installs the runtime for testing. Requires sudo.
@$(MAKE) configure RUNTIME=runsc
@$(MAKE) configure
@sudo systemctl restart docker
-.PHONY: install-test
+.PHONY: install-test-runtime
configure: ## Configures a single runtime. Requires sudo. Typically called from dev or test-install.
@sudo sudo "$(RUNTIME_BIN)" install --experimental=true --runtime="$(RUNTIME)" -- --debug-log "$(RUNTIME_LOGS)" $(ARGS)
diff --git a/WORKSPACE b/WORKSPACE
index b3e97b0cc..2ab750a9d 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -52,9 +52,6 @@ load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies", "go_repository")
gazelle_dependencies()
-# TODO(gvisor.dev/issue/1876): Move the statement to "External repositories"
-# block below once 1876 is fixed.
-#
# The com_google_protobuf repository below would trigger downloading a older
# version of org_golang_x_sys. If putting this repository statment in a place
# after that of the com_google_protobuf, this statement will not work as
@@ -190,12 +187,33 @@ http_archive(
],
)
-# Go repositories, in gazelle order.
+# External Go repositories.
+#
+# Unfortunately, gazelle will automatically parse go modules in the
+# repositories and generate new go_repository stanzas. These may not respect
+# pins that we have in go.mod or below. So order actually matters here.
+
+go_repository(
+ name = "com_github_sirupsen_logrus",
+ importpath = "github.com/sirupsen/logrus",
+ replace = "github.com/Sirupsen/logrus",
+ sum = "h1:cWjBmzJnL1sO88XdqJYmq7aiWClqXIQQMJ3Utgy1f+I=",
+ version = "v1.4.2",
+)
+
+go_repository(
+ name = "com_github_containerd_containerd",
+ build_file_proto_mode = "disable",
+ importpath = "github.com/containerd/containerd",
+ sum = "h1:3o0smo5SKY7H6AJCmJhsnCjR2/V2T8VmiHt7seN2/kI=",
+ version = "v1.3.4",
+)
+
go_repository(
name = "com_github_cenkalti_backoff",
importpath = "github.com/cenkalti/backoff",
- sum = "h1:+FKjzBIdfBHYDvxCv+djmDJdes/AoDtg8gpcxowBlF8=",
- version = "v0.0.0-20190506075156-2146c9339422",
+ sum = "h1:8eZxmY1yvxGHzdzTEhI09npjMVGzNAdrqzruTX6jcK4=",
+ version = "v1.1.1-0.20190506075156-2146c9339422",
)
go_repository(
@@ -208,43 +226,36 @@ go_repository(
go_repository(
name = "com_github_golang_mock",
importpath = "github.com/golang/mock",
- sum = "h1:G5FRp8JnTd7RQH5kemVNlMeyXQAztQ3mOWV95KxsXH8=",
- version = "v1.1.1",
-)
-
-go_repository(
- name = "com_github_google_go-cmp",
- importpath = "github.com/google/go-cmp",
- sum = "h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=",
- version = "v0.3.1",
+ sum = "h1:qGJ6qTW+x6xX/my+8YUVl4WNpX9B7+/l2tRsHGZ7f2s=",
+ version = "v1.3.1",
)
go_repository(
name = "com_github_google_subcommands",
importpath = "github.com/google/subcommands",
- sum = "h1:GZGUPQiZfYrd9uOqyqwbQcHPkz/EZJVkZB1MkaO9UBI=",
- version = "v0.0.0-20190508160503-636abe8753b8",
+ sum = "h1:8nlgEAjIalk6uj/CGKCdOO8CQqTeysvcW4RFZ6HbkGM=",
+ version = "v1.0.2-0.20190508160503-636abe8753b8",
)
go_repository(
name = "com_github_google_uuid",
importpath = "github.com/google/uuid",
- sum = "h1:rXQlD9GXkjA/PQZhmEaF/8Pj/sJfdZJK7GJG0gkS8I0=",
- version = "v0.0.0-20171129191014-dec09d789f3d",
+ sum = "h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA=",
+ version = "v1.0.0",
)
go_repository(
name = "com_github_kr_pretty",
importpath = "github.com/kr/pretty",
- sum = "h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=",
- version = "v0.2.0",
+ sum = "h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=",
+ version = "v0.1.0",
)
go_repository(
name = "com_github_kr_pty",
importpath = "github.com/kr/pty",
- sum = "h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw=",
- version = "v1.1.1",
+ sum = "h1:zc0R6cOw98cMengLA0fvU55mqbnN7sd/tBMLzSejp+M=",
+ version = "v1.1.4-0.20190131011033-7dc38fb350b1",
)
go_repository(
@@ -256,15 +267,9 @@ go_repository(
go_repository(
name = "com_github_mohae_deepcopy",
- commit = "c48cc78d482608239f6c4c92a4abd87eb8761c90",
importpath = "github.com/mohae/deepcopy",
-)
-
-go_repository(
- name = "com_github_opencontainers_runtime-spec",
- importpath = "github.com/opencontainers/runtime-spec",
- sum = "h1:UfAcuLBJB9Coz72x1hgl8O5RVzTdNiaglX6v2DM6FI0=",
- version = "v1.0.2",
+ sum = "h1:Sha2bQdoWE5YQPTlJOL31rmce94/tYi113SlFo1xQ2c=",
+ version = "v0.0.0-20170308212314-bb9b5e7adda9",
)
go_repository(
@@ -277,58 +282,51 @@ go_repository(
go_repository(
name = "com_github_vishvananda_netlink",
importpath = "github.com/vishvananda/netlink",
- sum = "h1:/Tdc23Arz1OtdIsBY2utWepGRQ9fEAJlhkdoLzWMK8Q=",
- version = "v1.0.1-0.20190318003149-adb577d4a45e",
-)
-
-go_repository(
- name = "com_github_vishvananda_netns",
- importpath = "github.com/vishvananda/netns",
- sum = "h1:J9gO8RJCAFlln1jsvRba/CWVUnMHwObklfxxjErl1uk=",
- version = "v0.0.0-20171111001504-be1fbeda1936",
+ sum = "h1:7SWt9pGCMaw+N1ZhRsaLKaYNviFhxambdoaoYlDqz1w=",
+ version = "v1.0.1-0.20190930145447-2ec5bdc52b86",
)
go_repository(
name = "org_golang_google_grpc",
build_file_proto_mode = "disable",
importpath = "google.golang.org/grpc",
- sum = "h1:Mm8atZtkT+P6R43n/dqNDWkPPu5BwRVu/1rJnJCeZH8=",
- version = "v1.12.0",
+ sum = "h1:2pJjwYOdkZ9HlN4sWRYBg9ttH5bCOlsueaM+b/oYjwo=",
+ version = "v1.29.0",
)
go_repository(
name = "in_gopkg_check_v1",
importpath = "gopkg.in/check.v1",
- sum = "h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=",
- version = "v1.0.0-20190902080502-41f04d3bba15",
+ sum = "h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=",
+ version = "v1.0.0-20180628173108-788fd7840127",
)
go_repository(
name = "org_golang_x_crypto",
importpath = "golang.org/x/crypto",
- sum = "h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=",
- version = "v0.0.0-20190308221718-c2843e01d9a2",
+ sum = "h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=",
+ version = "v0.0.0-20200622213623-75b288015ac9",
)
go_repository(
name = "org_golang_x_mod",
importpath = "golang.org/x/mod",
- sum = "h1:p1YOIz9H/mGN8k1XkaV5VFAq9+zhN9Obefv439UwRhI=",
- version = "v0.2.1-0.20200224194123-e5e73c1b9c72",
+ sum = "h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=",
+ version = "v0.3.0",
)
go_repository(
name = "org_golang_x_net",
importpath = "golang.org/x/net",
- sum = "h1:FCqk7JXVeupwwnGVopQCC0a0xRK0Rj7SL5AyjjWo4pk=",
- version = "v0.0.0-20170716174642-b3756b4b77d7",
+ sum = "h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4=",
+ version = "v0.0.0-20200625001655-4c5254603344",
)
go_repository(
name = "org_golang_x_sync",
importpath = "golang.org/x/sync",
- sum = "h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=",
- version = "v0.0.0-20190423024810-112230192c58",
+ sum = "h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA=",
+ version = "v0.0.0-20200625203802-6e8e738ad208",
)
go_repository(
@@ -348,15 +346,15 @@ go_repository(
go_repository(
name = "org_golang_x_tools",
importpath = "golang.org/x/tools",
- sum = "h1:NIou6eNFigscvKJmsbyez16S2cIS6idossORlFtSt2E=",
- version = "v0.0.0-20181030221726-6c7e314b6563",
+ sum = "h1:YAl/dx/kLsMMIWGqfhFHW9ckqGhmq7Ki0dfoKAgvFTE=",
+ version = "v0.0.0-20200707200213-416e8f4faf8a",
)
go_repository(
name = "org_golang_x_xerrors",
importpath = "golang.org/x/xerrors",
- sum = "h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc=",
- version = "v0.0.0-20190717185122-a985d3407aa7",
+ sum = "h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=",
+ version = "v0.0.0-20191204190536-9bdfabe68543",
)
go_repository(
@@ -369,51 +367,29 @@ go_repository(
go_repository(
name = "com_github_golang_protobuf",
importpath = "github.com/golang/protobuf",
- sum = "h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=",
- version = "v1.3.1",
-)
-
-go_repository(
- name = "com_github_google_go-github",
- importpath = "github.com/google/go-github",
- sum = "h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=",
- version = "v17.0.0",
+ sum = "h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=",
+ version = "v1.4.2",
)
go_repository(
name = "org_golang_x_oauth2",
importpath = "golang.org/x/oauth2",
- sum = "h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs=",
- version = "v0.0.0-20180821212333-d2e6202438be",
-)
-
-go_repository(
- name = "com_github_google_go-querystring",
- importpath = "github.com/google/go-querystring",
- sum = "h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=",
- version = "v1.0.0",
-)
-
-go_repository(
- name = "com_google_cloud_go_bigquery",
- importpath = "cloud.google.com/go/bigquery",
- sum = "h1:K2NyuHRuv15ku6eUpe0DQk5ZykPMnSOnvuVf6IHcjaE=",
- version = "v1.5.0",
+ sum = "h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw=",
+ version = "v0.0.0-20200107190931-bf48bf16ab8d",
)
-# Docker API dependencies.
go_repository(
name = "com_github_docker_docker",
importpath = "github.com/docker/docker",
- sum = "h1:iWPIG7pWIsCwT6ZtHnTUpoVMnete7O/pzd9HFE3+tn8=",
- version = "v17.12.0-ce-rc1.0.20200618181300-9dc6525e6118+incompatible",
+ sum = "h1:5AkIsnQpeL7eaqsM+Vl4Xbj5eIZFpPZZzXtNyfzzK/w=",
+ version = "v1.4.2-0.20191028175130-9e7d5ac5ea55",
)
go_repository(
name = "com_github_docker_go_connections",
importpath = "github.com/docker/go-connections",
- sum = "h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=",
- version = "v0.4.0",
+ sum = "h1:3lOnM9cSzgGwx8VfK/NGOW5fLQ0GjIlCkaktF+n1M6o=",
+ version = "v0.3.0",
)
go_repository(
@@ -440,8 +416,8 @@ go_repository(
go_repository(
name = "com_github_docker_distribution",
importpath = "github.com/docker/distribution",
- sum = "h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=",
- version = "v2.7.1+incompatible",
+ sum = "h1:dvc1KSkIYTVjZgHf/CTC2diTYC8PzhaA5sFISRfNVrE=",
+ version = "v2.7.1-0.20190205005809-0d3efadf0154+incompatible",
)
go_repository(
@@ -454,8 +430,8 @@ go_repository(
go_repository(
name = "com_github_konsorten_go_windows_terminal_sequences",
importpath = "github.com/konsorten/go-windows-terminal-sequences",
- sum = "h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=",
- version = "v2.7.1+incompatible",
+ sum = "h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=",
+ version = "v1.0.2",
)
go_repository(
@@ -466,17 +442,10 @@ go_repository(
)
go_repository(
- name = "com_github_sirupsen_logrus",
- importpath = "github.com/sirupsen/logrus",
- sum = "h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=",
- version = "v1.6.0",
-)
-
-go_repository(
name = "com_github_stretchr_testify",
importpath = "github.com/stretchr/testify",
- sum = "h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=",
- version = "v1.2.2",
+ sum = "h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=",
+ version = "v1.4.0",
)
go_repository(
@@ -487,17 +456,10 @@ go_repository(
)
go_repository(
- name = "com_github_containerd_containerd",
- importpath = "github.com/containerd/containerd",
- sum = "h1:3o0smo5SKY7H6AJCmJhsnCjR2/V2T8VmiHt7seN2/kI=",
- version = "v1.3.4",
-)
-
-go_repository(
name = "com_github_microsoft_go_winio",
importpath = "github.com/Microsoft/go-winio",
- sum = "h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU=",
- version = "v0.4.14",
+ sum = "h1:ygIc8M6trr62pF5DucadTWGdEB4mEyvzi0e2nbcmcyA=",
+ version = "v0.4.15-0.20190919025122-fc70bd9a86b5",
)
go_repository(
@@ -508,13 +470,6 @@ go_repository(
)
go_repository(
- name = "org_golang_google_api",
- importpath = "google.golang.org/api",
- sum = "h1:jz2KixHX7EcCPiQrySzPdnYT7DbINAypCqKZ1Z7GM40=",
- version = "v0.20.0",
-)
-
-go_repository(
name = "org_uber_go_atomic",
importpath = "go.uber.org/atomic",
sum = "h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk=",
@@ -524,36 +479,36 @@ go_repository(
go_repository(
name = "org_uber_go_multierr",
importpath = "go.uber.org/multierr",
- sum = "h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A=",
- version = "v1.5.0",
+ sum = "h1:6I+W7f5VwC5SV9dNrZ3qXrDB9mD0dyGOi/ZJmYw03T4=",
+ version = "v1.2.0",
)
go_repository(
name = "com_google_cloud_go",
importpath = "cloud.google.com/go",
- sum = "h1:e0WKqKTd5BnrG8aKH3J3h+QvEIQtSUcf2n5UZ5ZgLtQ=",
- version = "v0.26.0",
+ sum = "h1:Fvo/6MiAbwmQpsq5YFRo8O6TC40m9MK4Xh/oN07rIlo=",
+ version = "v0.52.1-0.20200122224058-0482b626c726",
)
go_repository(
- name = "com_github_googleapis_gax_go_v2",
- importpath = "github.com/googleapis/gax-go/v2",
- sum = "h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=",
- version = "v2.0.5",
+ name = "io_opencensus_go",
+ importpath = "go.opencensus.io",
+ sum = "h1:75k/FF0Q2YM8QYo07VPddOLBslDt1MZOdEslOHvmzAs=",
+ version = "v0.22.2",
)
go_repository(
- name = "io_opencensus_go",
- importpath = "go.opencensus.io",
- sum = "h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4=",
- version = "v0.22.0",
+ name = "co_honnef_go_tools",
+ importpath = "honnef.co/go/tools",
+ sum = "h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=",
+ version = "v0.0.1-2019.2.3",
)
go_repository(
- name = "com_github_golang_groupcache",
- importpath = "github.com/golang/groupcache",
- sum = "h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=",
- version = "v0.0.0-20200121045136-8c9f03a8e57e",
+ name = "com_github_burntsushi_toml",
+ importpath = "github.com/BurntSushi/toml",
+ sum = "h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=",
+ version = "v0.3.1",
)
go_repository(
@@ -577,86 +532,47 @@ go_repository(
version = "v0.0.0-20191209042840-269d4d468f6f",
)
-# K8s must be pinned to 1.14, prior to APIs being split into separate
-# repositories. The containerd versions below assume the existence of the cri
-# API within the kubelet package.
-go_repository(
- name = "io_k8s_kubernetes",
- importpath = "k8s.io/kubernetes",
- sum = "h1:6T2iAEoOYQnzQb3WvPlUkcczEEXZ7+YPlAO8olwujRw=",
- version = "v1.14.0",
-)
-
go_repository(
name = "com_github_containerd_cgroups",
build_file_proto_mode = "disable",
importpath = "github.com/containerd/cgroups",
- sum = "h1:5/YbYIVboEqSpFSC/iMO9FOIP/q8RIuKfYS2TA1M8WE=",
- version = "v0.0.0-20200520162414-666f4a009ffb",
+ sum = "h1:5yg0k8gqOssNLsjjCtXIADoPbAtUtQZJfC8hQ4r2oFY=",
+ version = "v0.0.0-20181219155423-39b18af02c41",
)
go_repository(
name = "com_github_containerd_console",
- build_file_proto_mode = "disable",
importpath = "github.com/containerd/console",
- sum = "h1:uict5mhHFTzKLUCufdSLym7z/J0CbBJT59lYbP9wtbg=",
- version = "v0.0.0-20180822173158-c12b1e7919c1",
-)
-
-go_repository(
- name = "com_github_containerd_containerd",
- build_file_proto_mode = "disable",
- importpath = "github.com/containerd/containerd",
- sum = "h1:BmZa1bGjKctYrIbyjbhZJlGvHceJASpdW5pIDSQcw1E=",
- version = "v0.0.0-20190510190154-d0319ec44af6",
+ sum = "h1:GdiIYd8ZDOrT++e1NjhSD4rGt9zaJukHm4rt5F4mRQc=",
+ version = "v0.0.0-20191206165004-02ecf6a7291e",
)
go_repository(
name = "com_github_containerd_continuity",
- build_file_proto_mode = "disable",
importpath = "github.com/containerd/continuity",
- sum = "h1:tN9D97v5A5QuKdcKHKt+UMKrkQ5YXUnD8iM7IAAjEfI=",
- version = "v0.0.0-20190815185530-f2a389ac0a02",
-)
-
-go_repository(
- name = "com_github_containerd_cri",
- build_file_proto_mode = "disable",
- importpath = "github.com/containerd/cri",
- sum = "h1:+bW7GQb2q32/Liy0ZiR6pkpRXdDHShUXRoWg8OGVWZs=",
- version = "v0.0.0-20190308093238-8a0bd84b9a4c",
+ sum = "h1:PEmIrUvwG9Yyv+0WKZqjXfSFDeZjs/q15g0m08BYS9k=",
+ version = "v0.0.0-20200710164510-efbc4488d8fe",
)
go_repository(
name = "com_github_containerd_fifo",
- build_file_proto_mode = "disable",
importpath = "github.com/containerd/fifo",
- sum = "h1:XGyg7oTtD0DoRFhbpV6x1WfV0flKC4UxXU7ab1zC08U=",
- version = "v0.0.0-20180307165137-3d5202aec260",
+ sum = "h1:lsjC5ENBl+Zgf38+B0ymougXFp0BaubeIVETltYZTQw=",
+ version = "v0.0.0-20191213151349-ff969a566b00",
)
go_repository(
name = "com_github_containerd_go_runc",
- build_file_proto_mode = "disable",
importpath = "github.com/containerd/go-runc",
- sum = "h1:esQOJREg8nw8aXj6uCN5dfW5cKUBiEJ/+nni1Q/D/sw=",
- version = "v0.0.0-20180907222934-5a6d9f37cfa3",
+ sum = "h1:PRTagVMbJcCezLcHXe8UJvR1oBzp2lG3CEumeFOLOds=",
+ version = "v0.0.0-20200220073739-7016d3ce2328",
)
go_repository(
name = "com_github_containerd_ttrpc",
- build_file_proto_mode = "disable",
importpath = "github.com/containerd/ttrpc",
- sum = "h1:SKDlsIhYxNE1LO0xwuOR+3QWj3zRibVQu5jWIMQmOfU=",
- version = "v0.0.0-20190411181408-699c4e40d1e7",
-)
-
-go_repository(
- name = "com_github_containerd_typeurl",
- build_file_proto_mode = "disable",
- importpath = "github.com/containerd/typeurl",
- sum = "h1:JNn81o/xG+8NEo3bC/vx9pbi/g2WI8mtP2/nXzu297Y=",
- version = "v0.0.0-20180627222232-a93fcdb778cd",
+ sum = "h1:+jgiLE5QylzgADj0Yldb4id1NQNRrDOROj7KDvY9PEc=",
+ version = "v0.0.0-20200121165050-0be804eadb15",
)
go_repository(
@@ -667,20 +583,6 @@ go_repository(
)
go_repository(
- name = "com_github_davecgh_go_spew",
- importpath = "github.com/davecgh/go-spew",
- sum = "h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=",
- version = "v1.1.1",
-)
-
-go_repository(
- name = "com_github_docker_distribution",
- importpath = "github.com/docker/distribution",
- sum = "h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=",
- version = "v2.7.1+incompatible",
-)
-
-go_repository(
name = "com_github_docker_go_events",
importpath = "github.com/docker/go-events",
sum = "h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8=",
@@ -688,13 +590,6 @@ go_repository(
)
go_repository(
- name = "com_github_docker_go_units",
- importpath = "github.com/docker/go-units",
- sum = "h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=",
- version = "v0.4.0",
-)
-
-go_repository(
name = "com_github_dustin_go_humanize",
importpath = "github.com/dustin/go-humanize",
sum = "h1:qk/FSDDxo05wdJH28W+p5yivv7LuLYLRXPPD8KQCtZs=",
@@ -725,8 +620,8 @@ go_repository(
go_repository(
name = "com_github_godbus_dbus",
importpath = "github.com/godbus/dbus",
- sum = "h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0=",
- version = "v0.0.0-20190726142602-4481cbc300e2",
+ sum = "h1:BWhy2j3IXJhjCbC68FptL43tDKIq8FladmaTs3Xs7Z8=",
+ version = "v0.0.0-20190422162347-ade71ed3457e",
)
go_repository(
@@ -751,6 +646,27 @@ go_repository(
)
go_repository(
+ name = "com_github_google_go_cmp",
+ importpath = "github.com/google/go-cmp",
+ sum = "h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=",
+ version = "v0.5.0",
+)
+
+go_repository(
+ name = "com_github_google_go_github_v28",
+ importpath = "github.com/google/go-github/v28",
+ sum = "h1:zOOUQavr8D4AZrcV4ylUpbGa5j3jfeslN6Xculz3tVU=",
+ version = "v28.1.2-0.20191108005307-e555eab49ce8",
+)
+
+go_repository(
+ name = "com_github_google_go_querystring",
+ importpath = "github.com/google/go-querystring",
+ sum = "h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=",
+ version = "v1.0.0",
+)
+
+go_repository(
name = "com_github_hashicorp_golang_lru",
importpath = "github.com/hashicorp/golang-lru",
sum = "h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=",
@@ -786,20 +702,6 @@ go_repository(
)
go_repository(
- name = "com_github_konsorten_go_windows_terminal_sequences",
- importpath = "github.com/konsorten/go-windows-terminal-sequences",
- sum = "h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=",
- version = "v1.0.2",
-)
-
-go_repository(
- name = "com_github_microsoft_go_winio",
- importpath = "github.com/Microsoft/go-winio",
- sum = "h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU=",
- version = "v0.4.14",
-)
-
-go_repository(
name = "com_github_microsoft_hcsshim",
importpath = "github.com/Microsoft/hcsshim",
sum = "h1:ZfF0+zZeYdzMIVMZHKtDKJvLHj76XCuVae/jNkjj0IA=",
@@ -821,38 +723,24 @@ go_repository(
)
go_repository(
- name = "com_github_opencontainers_go_digest",
- importpath = "github.com/opencontainers/go-digest",
- sum = "h1:QhPf3A2AZW3tTGvHPg0TA+CR3oHbVLlXUhlghqISp1I=",
- version = "v0.0.0-20180430190053-c9281466c8b2",
-)
-
-go_repository(
- name = "com_github_opencontainers_image_spec",
- importpath = "github.com/opencontainers/image-spec",
- sum = "h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=",
- version = "v1.0.1",
-)
-
-go_repository(
name = "com_github_opencontainers_runc",
importpath = "github.com/opencontainers/runc",
- sum = "h1:dDCFes8Hj1r/i5qnypONo5jdOme/8HWZC/aNDyhECt0=",
- version = "v1.0.0-rc8",
+ sum = "h1:GlxAyO6x8rfZYN9Tt0Kti5a/cP41iuiO2yYT0IJGY8Y=",
+ version = "v0.1.1",
)
go_repository(
- name = "com_github_pkg_errors",
- importpath = "github.com/pkg/errors",
- sum = "h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=",
- version = "v0.9.1",
+ name = "com_github_opencontainers_runtime_spec",
+ importpath = "github.com/opencontainers/runtime-spec",
+ sum = "h1:Pyp2f/uuhJIcUgnIeZaAbwOcyNz8TBlEe6mPpC8kXq8=",
+ version = "v1.0.2-0.20181111125026-1722abf79c2f",
)
go_repository(
- name = "com_github_pmezard_go_difflib",
- importpath = "github.com/pmezard/go-difflib",
- sum = "h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=",
- version = "v1.0.0",
+ name = "com_github_pborman_uuid",
+ importpath = "github.com/pborman/uuid",
+ sum = "h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g=",
+ version = "v1.2.0",
)
go_repository(
@@ -865,15 +753,8 @@ go_repository(
go_repository(
name = "com_github_prometheus_procfs",
importpath = "github.com/prometheus/procfs",
- sum = "h1:hhvfGDVThBnd4kYisSFmYuHYeUhglxcwag7FhVPH9zM=",
- version = "v0.0.0-20180125133057-cb4147076ac7",
-)
-
-go_repository(
- name = "com_github_sirupsen_logrus",
- importpath = "github.com/sirupsen/logrus",
- sum = "h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=",
- version = "v1.4.2",
+ sum = "h1:Lo6mRUjdS99f3zxYOUalftWHUoOGaDRqFk1+j0Q57/I=",
+ version = "v0.0.0-20190522114515-bc1a522cf7b1",
)
go_repository(
@@ -891,24 +772,17 @@ go_repository(
)
go_repository(
- name = "com_github_stretchr_objx",
- importpath = "github.com/stretchr/objx",
- sum = "h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=",
- version = "v0.1.1",
-)
-
-go_repository(
- name = "com_github_stretchr_testify",
- importpath = "github.com/stretchr/testify",
- sum = "h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=",
- version = "v1.2.2",
+ name = "com_github_urfave_cli",
+ importpath = "github.com/urfave/cli",
+ sum = "h1:MCfT24H3f//U5+UCrZp1/riVO3B50BovxtDiNn0XKkk=",
+ version = "v0.0.0-20171014202726-7bc6a0acffa5",
)
go_repository(
- name = "com_github_urfave_cli",
- importpath = "github.com/urfave/cli",
- sum = "h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo=",
- version = "v1.22.2",
+ name = "com_github_yuin_goldmark",
+ importpath = "github.com/yuin/goldmark",
+ sum = "h1:5tjfNdR2ki3yYQ842+eX2sQHeiwpKJ0RnHO4IYOc4V8=",
+ version = "v1.1.32",
)
go_repository(
@@ -942,8 +816,8 @@ go_repository(
go_repository(
name = "in_gopkg_yaml_v2",
importpath = "gopkg.in/yaml.v2",
- sum = "h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=",
- version = "v2.2.2",
+ sum = "h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=",
+ version = "v2.2.8",
)
go_repository(
@@ -956,29 +830,36 @@ go_repository(
go_repository(
name = "org_golang_google_appengine",
importpath = "google.golang.org/appengine",
- sum = "h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=",
- version = "v1.4.0",
+ sum = "h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM=",
+ version = "v1.6.5",
)
go_repository(
name = "org_golang_google_genproto",
importpath = "google.golang.org/genproto",
- sum = "h1:wVJP1pATLVPNxCz4R2mTO6HUJgfGE0PmIu2E10RuhCw=",
- version = "v0.0.0-20170523043604-d80a6e20e776",
+ sum = "h1:wDju+RU97qa0FZT0QnZDg9Uc2dH0Ql513kFvHocz+WM=",
+ version = "v0.0.0-20200117163144-32f20d992d24",
+)
+
+go_repository(
+ name = "org_golang_google_protobuf",
+ importpath = "google.golang.org/protobuf",
+ sum = "h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=",
+ version = "v1.23.0",
)
go_repository(
name = "org_golang_x_exp",
importpath = "golang.org/x/exp",
- sum = "h1:c2HOrn5iMezYjSlGPncknSEr/8x5LELb/ilJbXi9DEA=",
- version = "v0.0.0-20190121172915-509febef88a4",
+ sum = "h1:zQpM52jfKHG6II1ISZY1ZcpygvuSFZpLwfluuF89XOg=",
+ version = "v0.0.0-20191227195350-da58074b4299",
)
go_repository(
name = "org_golang_x_lint",
importpath = "golang.org/x/lint",
- sum = "h1:XQyxROzUlZH+WIQwySDgnISgOivlhjIEwaQaJEJrrN0=",
- version = "v0.0.0-20190313153728-d0100b6bd8b3",
+ sum = "h1:J5lckAjkw6qYlOZNj90mLYNTEKDvWeuc1yieZ8qUzUE=",
+ version = "v0.0.0-20191125180803-fdd1cda4f05f",
)
go_repository(
@@ -989,72 +870,190 @@ go_repository(
)
go_repository(
- name = "co_honnef_go_tools",
- importpath = "honnef.co/go/tools",
- sum = "h1:/hemPrYIhOhy8zYrNj+069zDB68us2sMGsfkFJO0iZs=",
- version = "v0.0.0-20190523083050-ea95bdfd59fc",
+ name = "com_github_burntsushi_xgb",
+ importpath = "github.com/BurntSushi/xgb",
+ sum = "h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc=",
+ version = "v0.0.0-20160522181843-27f122750802",
)
go_repository(
- name = "com_github_burntsushi_toml",
- importpath = "github.com/BurntSushi/toml",
- sum = "h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=",
- version = "v0.3.1",
+ name = "com_github_chzyer_logex",
+ importpath = "github.com/chzyer/logex",
+ sum = "h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=",
+ version = "v1.1.10",
)
go_repository(
- name = "io_k8s_cri_api",
- importpath = "k8s.io/cri-api",
- sum = "h1:bykYbClh5Bnjo2EMjlYbYQ3ksxHjjLcbriKPm831hVk=",
- version = "v0.18.2",
+ name = "com_github_chzyer_readline",
+ importpath = "github.com/chzyer/readline",
+ sum = "h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=",
+ version = "v0.0.0-20180603132655-2972be24d48e",
)
go_repository(
- name = "com_github_docker_docker",
- importpath = "github.com/docker/docker",
- sum = "h1:Bh3QS4GYuVi8QeNskrV3ivn8p0bupmk0PfY4xmVulo4=",
- version = "v17.12.0-ce-rc1.0.20200514230353-811a247d06e8+incompatible",
+ name = "com_github_chzyer_test",
+ importpath = "github.com/chzyer/test",
+ sum = "h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=",
+ version = "v0.0.0-20180213035817-a1ea475d72b1",
)
go_repository(
- name = "com_github_cilium_ebpf",
- importpath = "github.com/cilium/ebpf",
- sum = "h1:i8+1fuPLjSgAYXUyBlHNhFwjcfAsP4ufiuH1+PWkyDU=",
- version = "v0.0.0-20200110133405-4032b1d8aae3",
+ name = "com_github_go_gl_glfw_v3_3_glfw",
+ importpath = "github.com/go-gl/glfw/v3.3/glfw",
+ sum = "h1:b+9H1GAsx5RsjvDFLoS5zkNBzIQMuVKUYQDmxU3N5XE=",
+ version = "v0.0.0-20191125211704-12ad95a8df72",
)
go_repository(
- name = "com_github_coreos_go_systemd_v22",
- importpath = "github.com/coreos/go-systemd/v22",
- sum = "h1:XJIw/+VlJ+87J+doOxznsAWIdmWuViOVhkQamW5YV28=",
- version = "v22.0.0",
+ name = "com_github_golang_groupcache",
+ importpath = "github.com/golang/groupcache",
+ sum = "h1:5ZkaAPbicIKTF2I64qf5Fh8Aa83Q/dnOafMYV0OMwjA=",
+ version = "v0.0.0-20191227052852-215e87163ea7",
+)
+
+go_repository(
+ name = "com_github_google_martian",
+ importpath = "github.com/google/martian",
+ sum = "h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=",
+ version = "v2.1.0+incompatible",
+)
+
+go_repository(
+ name = "com_github_google_pprof",
+ importpath = "github.com/google/pprof",
+ sum = "h1:DLpL8pWq0v4JYoRpEhDfsJhhJyGKCcQM2WPW2TJs31c=",
+ version = "v0.0.0-20191218002539-d4f498aebedc",
+)
+
+go_repository(
+ name = "com_github_google_renameio",
+ importpath = "github.com/google/renameio",
+ sum = "h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA=",
+ version = "v0.1.0",
+)
+
+go_repository(
+ name = "com_github_googleapis_gax_go_v2",
+ importpath = "github.com/googleapis/gax-go/v2",
+ sum = "h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=",
+ version = "v2.0.5",
)
go_repository(
- name = "com_github_cpuguy83_go_md2man_v2",
- importpath = "github.com/cpuguy83/go-md2man/v2",
- sum = "h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=",
- version = "v2.0.0",
+ name = "com_github_ianlancetaylor_demangle",
+ importpath = "github.com/ianlancetaylor/demangle",
+ sum = "h1:UDMh68UUwekSh5iP2OMhRRZJiiBccgV7axzUG8vi56c=",
+ version = "v0.0.0-20181102032728-5e5cf60278f6",
)
go_repository(
- name = "com_github_godbus_dbus_v5",
- importpath = "github.com/godbus/dbus/v5",
- sum = "h1:ZqHaoEF7TBzh4jzPmqVhE/5A1z9of6orkAe5uHoAeME=",
- version = "v5.0.3",
+ name = "com_github_jstemmer_go_junit_report",
+ importpath = "github.com/jstemmer/go-junit-report",
+ sum = "h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o=",
+ version = "v0.9.1",
+)
+
+go_repository(
+ name = "com_github_rogpeppe_go_internal",
+ importpath = "github.com/rogpeppe/go-internal",
+ sum = "h1:RR9dF3JtopPvtkroDZuVD7qquD0bnHlKSqaQhgwt8yk=",
+ version = "v1.3.0",
+)
+
+go_repository(
+ name = "com_shuralyov_dmitri_gpu_mtl",
+ importpath = "dmitri.shuralyov.com/gpu/mtl",
+ sum = "h1:VpgP7xuJadIUuKccphEpTJnWhS2jkQyMt6Y7pJCD7fY=",
+ version = "v0.0.0-20190408044501-666a987793e9",
+)
+
+go_repository(
+ name = "in_gopkg_errgo_v2",
+ importpath = "gopkg.in/errgo.v2",
+ sum = "h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8=",
+ version = "v2.1.0",
)
go_repository(
- name = "com_github_russross_blackfriday_v2",
- importpath = "github.com/russross/blackfriday/v2",
- sum = "h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=",
- version = "v2.0.1",
+ name = "io_rsc_binaryregexp",
+ importpath = "rsc.io/binaryregexp",
+ sum = "h1:HfqmD5MEmC0zvwBuF187nq9mdnXjXsSivRiXN7SmRkE=",
+ version = "v0.2.0",
)
go_repository(
- name = "com_github_shurcool_sanitized_anchor_name",
- importpath = "github.com/shurcooL/sanitized_anchor_name",
- sum = "h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=",
+ name = "org_golang_google_api",
+ importpath = "google.golang.org/api",
+ sum = "h1:yzlyyDW/J0w8yNFJIhiAJy4kq74S+1DOLdawELNxFMA=",
+ version = "v0.15.0",
+)
+
+go_repository(
+ name = "org_golang_x_image",
+ importpath = "golang.org/x/image",
+ sum = "h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4=",
+ version = "v0.0.0-20190802002840-cff245a6509b",
+)
+
+go_repository(
+ name = "org_golang_x_mobile",
+ importpath = "golang.org/x/mobile",
+ sum = "h1:4+4C/Iv2U4fMZBiMCc98MG1In4gJY5YRhtpDNeDeHWs=",
+ version = "v0.0.0-20190719004257-d2bd2a29d028",
+)
+
+go_repository(
+ name = "com_github_containerd_typeurl",
+ importpath = "github.com/containerd/typeurl",
+ sum = "h1:HovfQDS/K3Mr7eyS0QJLxE1CbVUhjZCl6g3OhFJgP1o=",
+ version = "v0.0.0-20200205145503-b45ef1f1f737",
+)
+
+go_repository(
+ name = "com_github_vishvananda_netns",
+ importpath = "github.com/vishvananda/netns",
+ sum = "h1:mjAZxE1nh8yvuwhGHpdDqdhtNu2dgbpk93TwoXuk5so=",
+ version = "v0.0.0-20200520041808-52d707b772fe",
+)
+
+go_repository(
+ name = "com_google_cloud_go_bigquery",
+ importpath = "cloud.google.com/go/bigquery",
+ sum = "h1:hL+ycaJpVE9M7nLoiXb/Pn10ENE2u+oddxbD8uu0ZVU=",
+ version = "v1.0.1",
+)
+
+go_repository(
+ name = "com_google_cloud_go_datastore",
+ importpath = "cloud.google.com/go/datastore",
+ sum = "h1:Kt+gOPPp2LEPWp8CSfxhsM8ik9CcyE/gYu+0r+RnZvM=",
version = "v1.0.0",
)
+go_repository(
+ name = "com_google_cloud_go_pubsub",
+ importpath = "cloud.google.com/go/pubsub",
+ sum = "h1:W9tAK3E57P75u0XLLR82LZyw8VpAnhmyTOxW9qzmyj8=",
+ version = "v1.0.1",
+)
+
+go_repository(
+ name = "com_google_cloud_go_storage",
+ importpath = "cloud.google.com/go/storage",
+ sum = "h1:VV2nUM3wwLLGh9lSABFgZMjInyUbJeaRSE64WuAIQ+4=",
+ version = "v1.0.0",
+)
+
+go_repository(
+ name = "com_github_hashicorp_errwrap",
+ importpath = "github.com/hashicorp/errwrap",
+ sum = "h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=",
+ version = "v1.0.0",
+)
+
+go_repository(
+ name = "com_github_hashicorp_go_multierror",
+ importpath = "github.com/hashicorp/go-multierror",
+ sum = "h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=",
+ version = "v1.0.0",
+)
diff --git a/benchmarks/harness/BUILD b/benchmarks/harness/BUILD
index 48c548d59..2090d957a 100644
--- a/benchmarks/harness/BUILD
+++ b/benchmarks/harness/BUILD
@@ -10,7 +10,6 @@ pkg_tar(
srcs = [
"//tools/installers:head",
"//tools/installers:master",
- "//tools/installers:runsc",
],
mode = "0755",
)
diff --git a/g3doc/user_guide/runtimeclass.md b/g3doc/user_guide/runtimeclass.md
index 9f2d794c3..2e2d997be 100644
--- a/g3doc/user_guide/runtimeclass.md
+++ b/g3doc/user_guide/runtimeclass.md
@@ -3,13 +3,13 @@
First, follow the appropriate installation instructions for your version of
containerd.
-* For 1.1 or lower, use `gvisor-containerd-shim`.
-* For 1.2 or higher, use `containerd-shim-runsc-v1`.
+* For 1.1 or lower, use `gvisor-containerd-shim`.
+* For 1.2 or higher, use `containerd-shim-runsc-v1`.
# Set up the Kubernetes RuntimeClass
-Creating the RuntimeClass in kubernetes is simple once the runtime is available
-for containerd:
+Creating the [RuntimeClass][runtimeclass] in Kubernetes is simple once the
+runtime is available for containerd:
```shell
cat <<EOF | kubectl apply -f -
@@ -42,3 +42,5 @@ You can verify that the Pod is running via this RuntimeClass:
```shell
kubectl get pod nginx-gvisor -o wide
```
+
+[runtimeclass]: https://kubernetes.io/docs/concepts/containers/runtime-class/
diff --git a/go.mod b/go.mod
index ffc33a349..0875b4ba0 100644
--- a/go.mod
+++ b/go.mod
@@ -2,39 +2,51 @@ module gvisor.dev/gvisor
go 1.14
+replace github.com/Sirupsen/logrus => github.com/sirupsen/logrus v1.6.0
+
require (
- github.com/BurntSushi/toml v0.3.1
- github.com/Microsoft/go-winio v0.4.14 // indirect
+ cloud.google.com/go v0.52.1-0.20200122224058-0482b626c726 // indirect
+ github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5 // indirect
github.com/Microsoft/hcsshim v0.8.6 // indirect
- github.com/cenkalti/backoff v0.0.0-20190506075156-2146c9339422
- github.com/containerd/cgroups v0.0.0-20200520162414-666f4a009ffb
- github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1
- github.com/containerd/containerd v0.0.0-20190510190154-d0319ec44af6
- github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02 // indirect
- github.com/containerd/cri v0.0.0-20190308093238-8a0bd84b9a4c
- github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260
- github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3
- github.com/containerd/ttrpc v0.0.0-20190411181408-699c4e40d1e7 // indirect
- github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd
- github.com/gofrs/flock v0.6.1-0.20180915234121-886344bea079
- github.com/gogo/protobuf v1.3.1
- github.com/golang/protobuf v1.3.1
- github.com/google/btree v1.0.0
- github.com/google/go-cmp v0.3.1 // indirect
- github.com/google/subcommands v0.0.0-20190508160503-636abe8753b8
- github.com/kr/pretty v0.2.0 // indirect
- github.com/kr/pty v1.1.1
- github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2 // indirect
- github.com/opencontainers/runc v1.0.0-rc8 // indirect
- github.com/opencontainers/runtime-spec v1.0.2
- github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2
- github.com/vishvananda/netlink v1.0.1-0.20190318003149-adb577d4a45e
- github.com/vishvananda/netns v0.0.0-20171111001504-be1fbeda1936 // indirect
- golang.org/x/net v0.0.0-20170716174642-b3756b4b77d7 // indirect
- golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527
- golang.org/x/time v0.0.0-20191024005414-555d28b269f0
- google.golang.org/genproto v0.0.0-20170523043604-d80a6e20e776 // indirect
- google.golang.org/grpc v1.12.0
- gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
+ github.com/cenkalti/backoff v1.1.1-0.20190506075156-2146c9339422 // indirect
+ github.com/containerd/cgroups v0.0.0-20181219155423-39b18af02c41 // indirect
+ github.com/containerd/containerd v1.3.4 // indirect
+ github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe // indirect
+ github.com/containerd/fifo v0.0.0-20191213151349-ff969a566b00 // indirect
+ github.com/containerd/go-runc v0.0.0-20200220073739-7016d3ce2328 // indirect
+ github.com/containerd/ttrpc v0.0.0-20200121165050-0be804eadb15 // indirect
+ github.com/containerd/typeurl v0.0.0-20200205145503-b45ef1f1f737 // indirect
+ github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf // indirect
+ github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible // indirect
+ github.com/docker/docker v1.4.2-0.20191028175130-9e7d5ac5ea55 // indirect
+ github.com/docker/go-connections v0.3.0 // indirect
+ github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect
+ github.com/docker/go-units v0.4.0 // indirect
+ github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e // indirect
+ github.com/gofrs/flock v0.6.1-0.20180915234121-886344bea079 // indirect
+ github.com/gogo/googleapis v1.4.0 // indirect
+ github.com/golang/protobuf v1.4.2 // indirect
+ github.com/google/go-cmp v0.5.0 // indirect
+ github.com/google/go-github/v28 v28.1.2-0.20191108005307-e555eab49ce8 // indirect
+ github.com/google/subcommands v1.0.2-0.20190508160503-636abe8753b8 // indirect
+ github.com/hashicorp/go-multierror v1.0.0 // indirect
+ github.com/kr/pty v1.1.4-0.20190131011033-7dc38fb350b1 // indirect
+ github.com/mohae/deepcopy v0.0.0-20170308212314-bb9b5e7adda9 // indirect
+ github.com/opencontainers/go-digest v1.0.0 // indirect
+ github.com/opencontainers/image-spec v1.0.1 // indirect
+ github.com/opencontainers/runc v0.1.1 // indirect
+ github.com/opencontainers/runtime-spec v1.0.2-0.20181111125026-1722abf79c2f // indirect
+ github.com/pborman/uuid v1.2.0 // indirect
+ github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2 // indirect
+ github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5 // indirect
+ github.com/vishvananda/netlink v1.0.1-0.20190930145447-2ec5bdc52b86 // indirect
+ github.com/vishvananda/netns v0.0.0-20200520041808-52d707b772fe // indirect
+ go.uber.org/atomic v1.6.0 // indirect
+ go.uber.org/multierr v1.2.0 // indirect
+ golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 // indirect
+ golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect
+ golang.org/x/tools v0.0.0-20200707200213-416e8f4faf8a // indirect
+ google.golang.org/grpc v1.29.0 // indirect
+ gopkg.in/yaml.v2 v2.2.8 // indirect
gotest.tools v2.2.0+incompatible // indirect
)
diff --git a/go.sum b/go.sum
index 4212c6975..a90bca394 100644
--- a/go.sum
+++ b/go.sum
@@ -1,147 +1,384 @@
+bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8=
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
+cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
+cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
+cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
+cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
+cloud.google.com/go v0.52.1-0.20200122224058-0482b626c726 h1:Fvo/6MiAbwmQpsq5YFRo8O6TC40m9MK4Xh/oN07rIlo=
+cloud.google.com/go v0.52.1-0.20200122224058-0482b626c726/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
+cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
+cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
+cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
+cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
+dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU=
-github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU=
-github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
-github.com/Microsoft/hcsshim v0.8.6 h1:ZfF0+zZeYdzMIVMZHKtDKJvLHj76XCuVae/jNkjj0IA=
-github.com/Microsoft/hcsshim v0.8.6 h1:ZfF0+zZeYdzMIVMZHKtDKJvLHj76XCuVae/jNkjj0IA=
-github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
+github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5 h1:ygIc8M6trr62pF5DucadTWGdEB4mEyvzi0e2nbcmcyA=
+github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
-github.com/cenkalti/backoff v0.0.0-20190506075156-2146c9339422 h1:+FKjzBIdfBHYDvxCv+djmDJdes/AoDtg8gpcxowBlF8=
-github.com/cenkalti/backoff v0.0.0-20190506075156-2146c9339422/go.mod h1:b6Nc7NRH5C4aCISLry0tLnTjcuTEvoiqcWDdsU0sOGM=
-github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg=
-github.com/containerd/cgroups v0.0.0-20200520162414-666f4a009ffb h1:5/YbYIVboEqSpFSC/iMO9FOIP/q8RIuKfYS2TA1M8WE=
-github.com/containerd/cgroups v0.0.0-20200520162414-666f4a009ffb/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM=
-github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1 h1:uict5mhHFTzKLUCufdSLym7z/J0CbBJT59lYbP9wtbg=
-github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1 h1:uict5mhHFTzKLUCufdSLym7z/J0CbBJT59lYbP9wtbg=
+github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ=
+github.com/Microsoft/hcsshim v0.8.8/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8=
+github.com/Microsoft/hcsshim v0.8.9 h1:VrfodqvztU8YSOvygU+DN1BGaSGxmrNfqOv5oOuX2Bk=
+github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8=
+github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
+github.com/cenkalti/backoff v1.1.1-0.20190506075156-2146c9339422 h1:8eZxmY1yvxGHzdzTEhI09npjMVGzNAdrqzruTX6jcK4=
+github.com/cenkalti/backoff v1.1.1-0.20190506075156-2146c9339422/go.mod h1:b6Nc7NRH5C4aCISLry0tLnTjcuTEvoiqcWDdsU0sOGM=
+github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
+github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
+github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
+github.com/containerd/cgroups v0.0.0-20181219155423-39b18af02c41 h1:5yg0k8gqOssNLsjjCtXIADoPbAtUtQZJfC8hQ4r2oFY=
+github.com/containerd/cgroups v0.0.0-20181219155423-39b18af02c41/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI=
+github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f h1:tSNMc+rJDfmYntojat8lljbt1mgKNpTxUZJsSzJ9Y1s=
+github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko=
github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
-github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
-github.com/containerd/containerd v0.0.0-20190510190154-d0319ec44af6 h1:BmZa1bGjKctYrIbyjbhZJlGvHceJASpdW5pIDSQcw1E=
-github.com/containerd/containerd v0.0.0-20190510190154-d0319ec44af6 h1:BmZa1bGjKctYrIbyjbhZJlGvHceJASpdW5pIDSQcw1E=
-github.com/containerd/containerd v0.0.0-20190510190154-d0319ec44af6/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
-github.com/containerd/containerd v0.0.0-20190510190154-d0319ec44af6/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
-github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02 h1:tN9D97v5A5QuKdcKHKt+UMKrkQ5YXUnD8iM7IAAjEfI=
-github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
-github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
-github.com/containerd/cri v0.0.0-20190308093238-8a0bd84b9a4c h1:+bW7GQb2q32/Liy0ZiR6pkpRXdDHShUXRoWg8OGVWZs=
-github.com/containerd/cri v0.0.0-20190308093238-8a0bd84b9a4c/go.mod h1:DavH5Qa8+6jOmeOMO3dhWoqksucZDe06LfuhBz/xPZs=
-github.com/containerd/cri v0.0.0-20190308093238-8a0bd84b9a4c/go.mod h1:DavH5Qa8+6jOmeOMO3dhWoqksucZDe06LfuhBz/xPZs=
-github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260 h1:XGyg7oTtD0DoRFhbpV6x1WfV0flKC4UxXU7ab1zC08U=
-github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260 h1:XGyg7oTtD0DoRFhbpV6x1WfV0flKC4UxXU7ab1zC08U=
-github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
-github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
-github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3 h1:esQOJREg8nw8aXj6uCN5dfW5cKUBiEJ/+nni1Q/D/sw=
-github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3 h1:esQOJREg8nw8aXj6uCN5dfW5cKUBiEJ/+nni1Q/D/sw=
-github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0=
+github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e h1:GdiIYd8ZDOrT++e1NjhSD4rGt9zaJukHm4rt5F4mRQc=
+github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE=
+github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
+github.com/containerd/containerd v1.3.4 h1:3o0smo5SKY7H6AJCmJhsnCjR2/V2T8VmiHt7seN2/kI=
+github.com/containerd/containerd v1.3.4/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
+github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
+github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe h1:PEmIrUvwG9Yyv+0WKZqjXfSFDeZjs/q15g0m08BYS9k=
+github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo=
+github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI=
+github.com/containerd/fifo v0.0.0-20191213151349-ff969a566b00 h1:lsjC5ENBl+Zgf38+B0ymougXFp0BaubeIVETltYZTQw=
+github.com/containerd/fifo v0.0.0-20191213151349-ff969a566b00/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0=
github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0=
-github.com/containerd/ttrpc v0.0.0-20190411181408-699c4e40d1e7 h1:SKDlsIhYxNE1LO0xwuOR+3QWj3zRibVQu5jWIMQmOfU=
-github.com/containerd/ttrpc v0.0.0-20190411181408-699c4e40d1e7 h1:SKDlsIhYxNE1LO0xwuOR+3QWj3zRibVQu5jWIMQmOfU=
-github.com/containerd/ttrpc v0.0.0-20190411181408-699c4e40d1e7/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
-github.com/containerd/ttrpc v0.0.0-20190411181408-699c4e40d1e7/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
-github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd h1:JNn81o/xG+8NEo3bC/vx9pbi/g2WI8mtP2/nXzu297Y=
-github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd h1:JNn81o/xG+8NEo3bC/vx9pbi/g2WI8mtP2/nXzu297Y=
+github.com/containerd/go-runc v0.0.0-20200220073739-7016d3ce2328 h1:PRTagVMbJcCezLcHXe8UJvR1oBzp2lG3CEumeFOLOds=
+github.com/containerd/go-runc v0.0.0-20200220073739-7016d3ce2328/go.mod h1:PpyHrqVs8FTi9vpyHwPwiNEGaACDxT/N/pLcvMSRA9g=
+github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
+github.com/containerd/ttrpc v0.0.0-20200121165050-0be804eadb15 h1:+jgiLE5QylzgADj0Yldb4id1NQNRrDOROj7KDvY9PEc=
+github.com/containerd/ttrpc v0.0.0-20200121165050-0be804eadb15/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y=
github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc=
-github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc=
-github.com/coreos/go-systemd/v22 v22.0.0 h1:XJIw/+VlJ+87J+doOxznsAWIdmWuViOVhkQamW5YV28=
-github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
-github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
-github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
-github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
-github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/containerd/typeurl v0.0.0-20200205145503-b45ef1f1f737 h1:HovfQDS/K3Mr7eyS0QJLxE1CbVUhjZCl6g3OhFJgP1o=
+github.com/containerd/typeurl v0.0.0-20200205145503-b45ef1f1f737/go.mod h1:TB1hUtrpaiO88KEK56ijojHS1+NeF0izUACaJW2mdXg=
+github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
+github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU=
+github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible h1:dvc1KSkIYTVjZgHf/CTC2diTYC8PzhaA5sFISRfNVrE=
+github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
+github.com/docker/docker v1.4.2-0.20191028175130-9e7d5ac5ea55 h1:5AkIsnQpeL7eaqsM+Vl4Xbj5eIZFpPZZzXtNyfzzK/w=
+github.com/docker/docker v1.4.2-0.20191028175130-9e7d5ac5ea55/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
+github.com/docker/go-connections v0.3.0 h1:3lOnM9cSzgGwx8VfK/NGOW5fLQ0GjIlCkaktF+n1M6o=
+github.com/docker/go-connections v0.3.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
+github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8=
+github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
-github.com/godbus/dbus/v5 v5.0.3 h1:ZqHaoEF7TBzh4jzPmqVhE/5A1z9of6orkAe5uHoAeME=
-github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
+github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
+github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
+github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
+github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
+github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e h1:BWhy2j3IXJhjCbC68FptL43tDKIq8FladmaTs3Xs7Z8=
+github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
github.com/gofrs/flock v0.6.1-0.20180915234121-886344bea079 h1:JFTFz3HZTGmgMz4E1TabNBNJljROSYgja1b4l50FNVs=
github.com/gofrs/flock v0.6.1-0.20180915234121-886344bea079/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
+github.com/gogo/googleapis v1.4.0 h1:zgVt4UpGxcqVOw97aRGxT4svlcmdK35fynLNctY32zI=
+github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c=
+github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
-github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7 h1:5ZkaAPbicIKTF2I64qf5Fh8Aa83Q/dnOafMYV0OMwjA=
+github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/mock v1.3.1 h1:qGJ6qTW+x6xX/my+8YUVl4WNpX9B7+/l2tRsHGZ7f2s=
+github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
+github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
+github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
+github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
+github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
+github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
-github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
+github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
-github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
-github.com/google/subcommands v0.0.0-20190508160503-636abe8753b8 h1:GZGUPQiZfYrd9uOqyqwbQcHPkz/EZJVkZB1MkaO9UBI=
-github.com/google/subcommands v0.0.0-20190508160503-636abe8753b8/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
+github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-github/v28 v28.1.2-0.20191108005307-e555eab49ce8 h1:zOOUQavr8D4AZrcV4ylUpbGa5j3jfeslN6Xculz3tVU=
+github.com/google/go-github/v28 v28.1.2-0.20191108005307-e555eab49ce8/go.mod h1:g82e6OHbJ0WYrYeOrid1MMfHAtqjxBz+N74tfAt9KrQ=
+github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
+github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
+github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
+github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
+github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
+github.com/google/subcommands v1.0.2-0.20190508160503-636abe8753b8 h1:8nlgEAjIalk6uj/CGKCdOO8CQqTeysvcW4RFZ6HbkGM=
+github.com/google/subcommands v1.0.2-0.20190508160503-636abe8753b8/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
+github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA=
+github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
+github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
+github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
+github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
+github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=
+github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
+github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
+github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
+github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
+github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
+github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o=
+github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
+github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
-github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
-github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
-github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
-github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
-github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
-github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
-github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
+github.com/kr/pty v1.1.4-0.20190131011033-7dc38fb350b1 h1:zc0R6cOw98cMengLA0fvU55mqbnN7sd/tBMLzSejp+M=
+github.com/kr/pty v1.1.4-0.20190131011033-7dc38fb350b1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
-github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2 h1:QhPf3A2AZW3tTGvHPg0TA+CR3oHbVLlXUhlghqISp1I=
+github.com/mohae/deepcopy v0.0.0-20170308212314-bb9b5e7adda9 h1:Sha2bQdoWE5YQPTlJOL31rmce94/tYi113SlFo1xQ2c=
+github.com/mohae/deepcopy v0.0.0-20170308212314-bb9b5e7adda9/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
+github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
-github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
-github.com/opencontainers/runc v1.0.0-rc8 h1:dDCFes8Hj1r/i5qnypONo5jdOme/8HWZC/aNDyhECt0=
-github.com/opencontainers/runc v1.0.0-rc8/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
-github.com/opencontainers/runc v1.0.0-rc8/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
-github.com/opencontainers/runtime-spec v1.0.2 h1:UfAcuLBJB9Coz72x1hgl8O5RVzTdNiaglX6v2DM6FI0=
-github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
-github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
-github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
+github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
+github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
+github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
+github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
+github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
+github.com/opencontainers/runc v0.1.1 h1:GlxAyO6x8rfZYN9Tt0Kti5a/cP41iuiO2yYT0IJGY8Y=
+github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
+github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
+github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
+github.com/opencontainers/runtime-spec v1.0.2-0.20181111125026-1722abf79c2f h1:Pyp2f/uuhJIcUgnIeZaAbwOcyNz8TBlEe6mPpC8kXq8=
+github.com/opencontainers/runtime-spec v1.0.2-0.20181111125026-1722abf79c2f/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
+github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g=
+github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
+github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
-github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
-github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
-github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
-github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k=
-github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
+github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
+github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
+github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
+github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
+github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
-github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2 h1:b6uOv7YOFK0TYG7HtkIgExQo+2RdLuwRft63jn2HWj8=
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
-github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
-github.com/vishvananda/netlink v1.0.1-0.20190318003149-adb577d4a45e h1:/Tdc23Arz1OtdIsBY2utWepGRQ9fEAJlhkdoLzWMK8Q=
-github.com/vishvananda/netlink v1.0.1-0.20190318003149-adb577d4a45e/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
-github.com/vishvananda/netns v0.0.0-20171111001504-be1fbeda1936 h1:J9gO8RJCAFlln1jsvRba/CWVUnMHwObklfxxjErl1uk=
-github.com/vishvananda/netns v0.0.0-20171111001504-be1fbeda1936/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI=
-golang.org/x/net v0.0.0-20170716174642-b3756b4b77d7 h1:FCqk7JXVeupwwnGVopQCC0a0xRK0Rj7SL5AyjjWo4pk=
-golang.org/x/net v0.0.0-20170716174642-b3756b4b77d7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20170716174642-b3756b4b77d7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
+github.com/vishvananda/netlink v1.0.1-0.20190930145447-2ec5bdc52b86 h1:7SWt9pGCMaw+N1ZhRsaLKaYNviFhxambdoaoYlDqz1w=
+github.com/vishvananda/netlink v1.0.1-0.20190930145447-2ec5bdc52b86/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
+github.com/vishvananda/netns v0.0.0-20200520041808-52d707b772fe h1:mjAZxE1nh8yvuwhGHpdDqdhtNu2dgbpk93TwoXuk5so=
+github.com/vishvananda/netns v0.0.0-20200520041808-52d707b772fe/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
+github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
+go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
+go.opencensus.io v0.22.2 h1:75k/FF0Q2YM8QYo07VPddOLBslDt1MZOdEslOHvmzAs=
+go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk=
+go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
+go.uber.org/multierr v1.2.0 h1:6I+W7f5VwC5SV9dNrZ3qXrDB9mD0dyGOi/ZJmYw03T4=
+go.uber.org/multierr v1.2.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
+golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
+golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
+golang.org/x/exp v0.0.0-20191227195350-da58074b4299 h1:zQpM52jfKHG6II1ISZY1ZcpygvuSFZpLwfluuF89XOg=
+golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
+golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
+golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
+golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f h1:J5lckAjkw6qYlOZNj90mLYNTEKDvWeuc1yieZ8qUzUE=
+golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
+golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
+golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
+golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
+golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
+golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
+golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
+golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4=
+golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw=
+golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA=
+golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b h1:ag/x1USPSsqHud38I9BAC88qdNLDHHtQ4mlgQIZPPNA=
+golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 h1:uYVVQ9WP/Ds2ROhcaGPeIdVq0RIXVLwsHlnvJ+cT1So=
-golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200523222454-059865788121 h1:rITEj+UZHYC927n8GT97eC3zrpzXdb/voyeOuVKS46o=
+golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-google.golang.org/genproto v0.0.0-20170523043604-d80a6e20e776 h1:wVJP1pATLVPNxCz4R2mTO6HUJgfGE0PmIu2E10RuhCw=
-google.golang.org/genproto v0.0.0-20170523043604-d80a6e20e776/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
-google.golang.org/genproto v0.0.0-20170523043604-d80a6e20e776/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
-google.golang.org/grpc v1.12.0 h1:Mm8atZtkT+P6R43n/dqNDWkPPu5BwRVu/1rJnJCeZH8=
-google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
-google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
+golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200707200213-416e8f4faf8a h1:YAl/dx/kLsMMIWGqfhFHW9ckqGhmq7Ki0dfoKAgvFTE=
+golang.org/x/tools v0.0.0-20200707200213-416e8f4faf8a/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
+google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
+google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
+google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
+google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
+google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM=
+google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
+google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200117163144-32f20d992d24 h1:wDju+RU97qa0FZT0QnZDg9Uc2dH0Ql513kFvHocz+WM=
+google.golang.org/genproto v0.0.0-20200117163144-32f20d992d24/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
+google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
+google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
+google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.29.0 h1:2pJjwYOdkZ9HlN4sWRYBg9ttH5bCOlsueaM+b/oYjwo=
+google.golang.org/grpc v1.29.0/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
+google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
+google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
+google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
+google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
+google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
+google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
-gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
+gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
+gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
+gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
-gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
+gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
+honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
+honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
+rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
diff --git a/images/benchmarks/absl/Dockerfile b/images/benchmarks/absl/Dockerfile
new file mode 100644
index 000000000..b0dd97695
--- /dev/null
+++ b/images/benchmarks/absl/Dockerfile
@@ -0,0 +1,21 @@
+FROM ubuntu:18.04
+
+RUN set -x \
+ && apt-get update \
+ && apt-get install -y \
+ wget \
+ git \
+ pkg-config \
+ zip \
+ g++ \
+ zlib1g-dev \
+ unzip \
+ python3 \
+ && rm -rf /var/lib/apt/lists/*
+RUN wget https://github.com/bazelbuild/bazel/releases/download/0.27.0/bazel-0.27.0-installer-linux-x86_64.sh
+RUN chmod +x bazel-0.27.0-installer-linux-x86_64.sh
+RUN ./bazel-0.27.0-installer-linux-x86_64.sh
+
+RUN mkdir abseil-cpp && cd abseil-cpp \
+ && git init && git remote add origin https://github.com/abseil/abseil-cpp.git \
+ && git fetch --depth 1 origin 43ef2148c0936ebf7cb4be6b19927a9d9d145b8f && git checkout FETCH_HEAD
diff --git a/images/benchmarks/iperf/Dockerfile b/images/benchmarks/iperf/Dockerfile
new file mode 100644
index 000000000..4cbfd0d70
--- /dev/null
+++ b/images/benchmarks/iperf/Dockerfile
@@ -0,0 +1,8 @@
+FROM ubuntu:18.04
+
+RUN set -x \
+ && apt-get update \
+ && apt-get install -y \
+ iperf \
+ && rm -rf /var/lib/apt/lists/*
+
diff --git a/pkg/sentry/fsimpl/ext/BUILD b/pkg/sentry/fsimpl/ext/BUILD
index ef24f8159..abc610ef3 100644
--- a/pkg/sentry/fsimpl/ext/BUILD
+++ b/pkg/sentry/fsimpl/ext/BUILD
@@ -96,7 +96,7 @@ go_test(
"//pkg/syserror",
"//pkg/test/testutil",
"//pkg/usermem",
- "@com_github_google_go-cmp//cmp:go_default_library",
- "@com_github_google_go-cmp//cmp/cmpopts:go_default_library",
+ "@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/gofer/gofer.go b/pkg/sentry/fsimpl/gofer/gofer.go
index 2b83094cd..b74d489a0 100644
--- a/pkg/sentry/fsimpl/gofer/gofer.go
+++ b/pkg/sentry/fsimpl/gofer/gofer.go
@@ -602,8 +602,14 @@ type dentry struct {
// returned by the server. dirents is protected by dirMu.
dirents []vfs.Dirent
- // Cached metadata; protected by metadataMu and accessed using atomic
- // memory operations unless otherwise specified.
+ // Cached metadata; protected by metadataMu.
+ // To access:
+ // - In situations where consistency is not required (like stat), these
+ // can be accessed using atomic operations only (without locking).
+ // - Lock metadataMu and can access without atomic operations.
+ // To mutate:
+ // - Lock metadataMu and use atomic operations to update because we might
+ // have atomic readers that don't hold the lock.
metadataMu sync.Mutex
ino inodeNumber // immutable
mode uint32 // type is immutable, perms are mutable
@@ -616,7 +622,7 @@ type dentry struct {
ctime int64
btime int64
// File size, protected by both metadataMu and dataMu (i.e. both must be
- // locked to mutate it).
+ // locked to mutate it; locking either is sufficient to access it).
size uint64
// nlink counts the number of hard links to this dentry. It's updated and
@@ -904,14 +910,14 @@ func (d *dentry) setStat(ctx context.Context, creds *auth.Credentials, stat *lin
// Prepare for truncate.
if stat.Mask&linux.STATX_SIZE != 0 {
- switch d.mode & linux.S_IFMT {
- case linux.S_IFREG:
+ switch mode.FileType() {
+ case linux.ModeRegular:
if !setLocalMtime {
// Truncate updates mtime.
setLocalMtime = true
stat.Mtime.Nsec = linux.UTIME_NOW
}
- case linux.S_IFDIR:
+ case linux.ModeDirectory:
return syserror.EISDIR
default:
return syserror.EINVAL
@@ -994,7 +1000,7 @@ func (d *dentry) setStat(ctx context.Context, creds *auth.Credentials, stat *lin
func (d *dentry) updateFileSizeLocked(newSize uint64) {
d.dataMu.Lock()
oldSize := d.size
- d.size = newSize
+ atomic.StoreUint64(&d.size, newSize)
// d.dataMu must be unlocked to lock d.mapsMu and invalidate mappings
// below. This allows concurrent calls to Read/Translate/etc. These
// functions synchronize with truncation by refusing to use cache
@@ -1340,8 +1346,8 @@ func (d *dentry) removexattr(ctx context.Context, creds *auth.Credentials, name
// Extended attributes in the user.* namespace are only supported for regular
// files and directories.
func (d *dentry) userXattrSupported() bool {
- filetype := linux.S_IFMT & atomic.LoadUint32(&d.mode)
- return filetype == linux.S_IFREG || filetype == linux.S_IFDIR
+ filetype := linux.FileMode(atomic.LoadUint32(&d.mode)).FileType()
+ return filetype == linux.ModeRegular || filetype == linux.ModeDirectory
}
// Preconditions: !d.isSynthetic(). d.isRegularFile() || d.isDir().
diff --git a/pkg/sentry/fsimpl/gofer/regular_file.go b/pkg/sentry/fsimpl/gofer/regular_file.go
index a2f02d9c7..f10350c97 100644
--- a/pkg/sentry/fsimpl/gofer/regular_file.go
+++ b/pkg/sentry/fsimpl/gofer/regular_file.go
@@ -89,7 +89,9 @@ func (fd *regularFileFD) Allocate(ctx context.Context, mode, offset, length uint
if err != nil {
return err
}
- d.size = size
+ d.dataMu.Lock()
+ atomic.StoreUint64(&d.size, size)
+ d.dataMu.Unlock()
if !d.cachedMetadataAuthoritative() {
d.touchCMtimeLocked()
}
diff --git a/pkg/sentry/fsimpl/kernfs/BUILD b/pkg/sentry/fsimpl/kernfs/BUILD
index 179df6c1e..3835557fe 100644
--- a/pkg/sentry/fsimpl/kernfs/BUILD
+++ b/pkg/sentry/fsimpl/kernfs/BUILD
@@ -70,6 +70,6 @@ go_test(
"//pkg/sentry/vfs",
"//pkg/syserror",
"//pkg/usermem",
- "@com_github_google_go-cmp//cmp:go_default_library",
+ "@com_github_google_go_cmp//cmp:go_default_library",
],
)
diff --git a/pkg/sentry/fsimpl/sys/BUILD b/pkg/sentry/fsimpl/sys/BUILD
index a741e2bb6..1b548ccd4 100644
--- a/pkg/sentry/fsimpl/sys/BUILD
+++ b/pkg/sentry/fsimpl/sys/BUILD
@@ -29,6 +29,6 @@ go_test(
"//pkg/sentry/kernel",
"//pkg/sentry/kernel/auth",
"//pkg/sentry/vfs",
- "@com_github_google_go-cmp//cmp:go_default_library",
+ "@com_github_google_go_cmp//cmp:go_default_library",
],
)
diff --git a/pkg/sentry/fsimpl/testutil/BUILD b/pkg/sentry/fsimpl/testutil/BUILD
index 0e4053a46..400a97996 100644
--- a/pkg/sentry/fsimpl/testutil/BUILD
+++ b/pkg/sentry/fsimpl/testutil/BUILD
@@ -32,6 +32,6 @@ go_library(
"//pkg/sentry/vfs",
"//pkg/sync",
"//pkg/usermem",
- "@com_github_google_go-cmp//cmp:go_default_library",
+ "@com_github_google_go_cmp//cmp:go_default_library",
],
)
diff --git a/pkg/sentry/kernel/timekeeper.go b/pkg/sentry/kernel/timekeeper.go
index 0adf25691..5f3908d8b 100644
--- a/pkg/sentry/kernel/timekeeper.go
+++ b/pkg/sentry/kernel/timekeeper.go
@@ -210,9 +210,6 @@ func (t *Timekeeper) startUpdater() {
p.realtimeBaseRef = int64(realtimeParams.BaseRef)
p.realtimeFrequency = realtimeParams.Frequency
}
-
- log.Debugf("Updating VDSO parameters: %+v", p)
-
return p
}); err != nil {
log.Warningf("Unable to update VDSO parameter page: %v", err)
diff --git a/pkg/sentry/platform/kvm/machine_arm64_unsafe.go b/pkg/sentry/platform/kvm/machine_arm64_unsafe.go
index 8bed34922..3de309c1a 100644
--- a/pkg/sentry/platform/kvm/machine_arm64_unsafe.go
+++ b/pkg/sentry/platform/kvm/machine_arm64_unsafe.go
@@ -78,19 +78,6 @@ func (c *vCPU) initArchState() error {
return err
}
- // sctlr_el1
- regGet.id = _KVM_ARM64_REGS_SCTLR_EL1
- if err := c.getOneRegister(&regGet); err != nil {
- return err
- }
-
- dataGet |= (_SCTLR_M | _SCTLR_C | _SCTLR_I)
- data = dataGet
- reg.id = _KVM_ARM64_REGS_SCTLR_EL1
- if err := c.setOneRegister(&reg); err != nil {
- return err
- }
-
// tcr_el1
data = _TCR_TXSZ_VA48 | _TCR_CACHE_FLAGS | _TCR_SHARED | _TCR_TG_FLAGS | _TCR_ASID16 | _TCR_IPS_40BITS
reg.id = _KVM_ARM64_REGS_TCR_EL1
diff --git a/pkg/sentry/platform/ring0/entry_arm64.s b/pkg/sentry/platform/ring0/entry_arm64.s
index 2bc5f3ecd..6ed73699b 100644
--- a/pkg/sentry/platform/ring0/entry_arm64.s
+++ b/pkg/sentry/platform/ring0/entry_arm64.s
@@ -40,6 +40,14 @@
#define FPEN_ENABLE (FPEN_NOTRAP << FPEN_SHIFT)
+// sctlr_el1: system control register el1.
+#define SCTLR_M 1 << 0
+#define SCTLR_C 1 << 2
+#define SCTLR_I 1 << 12
+#define SCTLR_UCT 1 << 15
+
+#define SCTLR_EL1_DEFAULT (SCTLR_M | SCTLR_C | SCTLR_I | SCTLR_UCT)
+
// Saves a register set.
//
// This is a macro because it may need to executed in contents where a stack is
@@ -496,6 +504,11 @@ TEXT ·kernelExitToEl1(SB),NOSPLIT,$0
// Start is the CPU entrypoint.
TEXT ·Start(SB),NOSPLIT,$0
IRQ_DISABLE
+
+ // Init.
+ MOVD $SCTLR_EL1_DEFAULT, R1
+ MSR R1, SCTLR_EL1
+
MOVD R8, RSV_REG
ORR $0xffff000000000000, RSV_REG, RSV_REG
WORD $0xd518d092 //MSR R18, TPIDR_EL1
diff --git a/pkg/sentry/socket/netstack/netstack.go b/pkg/sentry/socket/netstack/netstack.go
index 3b248a953..78a842973 100644
--- a/pkg/sentry/socket/netstack/netstack.go
+++ b/pkg/sentry/socket/netstack/netstack.go
@@ -192,6 +192,7 @@ var Metrics = tcpip.Stats{
PacketsSent: mustCreateMetric("/netstack/udp/packets_sent", "Number of UDP datagrams sent."),
PacketSendErrors: mustCreateMetric("/netstack/udp/packet_send_errors", "Number of UDP datagrams failed to be sent."),
ChecksumErrors: mustCreateMetric("/netstack/udp/checksum_errors", "Number of UDP datagrams dropped due to bad checksums."),
+ InvalidSourceAddress: mustCreateMetric("/netstack/udp/invalid_source", "Number of UDP datagrams dropped due to invalid source address."),
},
}
@@ -1753,6 +1754,11 @@ func setSockOptSocket(t *kernel.Task, s socket.SocketOps, ep commonEndpoint, nam
return nil
+ case linux.SO_DETACH_FILTER:
+ // optval is ignored.
+ var v tcpip.SocketDetachFilterOption
+ return syserr.TranslateNetstackError(ep.SetSockOpt(v))
+
default:
socket.SetSockOptEmitUnimplementedEvent(t, name)
}
diff --git a/pkg/sentry/time/parameters.go b/pkg/sentry/time/parameters.go
index 65868cb26..cd1b95117 100644
--- a/pkg/sentry/time/parameters.go
+++ b/pkg/sentry/time/parameters.go
@@ -228,11 +228,15 @@ func errorAdjust(prevParams Parameters, newParams Parameters, now TSCValue) (Par
//
// The log level is determined by the error severity.
func logErrorAdjustment(clock ClockID, errorNS ReferenceNS, orig, adjusted Parameters) {
- fn := log.Debugf
- if int64(errorNS.Magnitude()) > time.Millisecond.Nanoseconds() {
+ magNS := int64(errorNS.Magnitude())
+ if magNS <= 10*time.Microsecond.Nanoseconds() {
+ // Don't log small errors.
+ return
+ }
+ fn := log.Infof
+ if magNS > time.Millisecond.Nanoseconds() {
+ // Upgrade large errors to warning.
fn = log.Warningf
- } else if int64(errorNS.Magnitude()) > 10*time.Microsecond.Nanoseconds() {
- fn = log.Infof
}
fn("Clock(%v): error: %v ns, adjusted frequency from %v Hz to %v Hz", clock, errorNS, orig.Frequency, adjusted.Frequency)
diff --git a/pkg/sentry/vfs/inotify.go b/pkg/sentry/vfs/inotify.go
index c2e21ac5f..167b731ac 100644
--- a/pkg/sentry/vfs/inotify.go
+++ b/pkg/sentry/vfs/inotify.go
@@ -179,12 +179,12 @@ func (i *Inotify) Readiness(mask waiter.EventMask) waiter.EventMask {
return mask & ready
}
-// PRead implements FileDescriptionImpl.
+// PRead implements FileDescriptionImpl.PRead.
func (*Inotify) PRead(ctx context.Context, dst usermem.IOSequence, offset int64, opts ReadOptions) (int64, error) {
return 0, syserror.ESPIPE
}
-// PWrite implements FileDescriptionImpl.
+// PWrite implements FileDescriptionImpl.PWrite.
func (*Inotify) PWrite(ctx context.Context, src usermem.IOSequence, offset int64, opts WriteOptions) (int64, error) {
return 0, syserror.ESPIPE
}
@@ -243,7 +243,7 @@ func (i *Inotify) Read(ctx context.Context, dst usermem.IOSequence, opts ReadOpt
return writeLen, nil
}
-// Ioctl implements fs.FileOperations.Ioctl.
+// Ioctl implements FileDescriptionImpl.Ioctl.
func (i *Inotify) Ioctl(ctx context.Context, uio usermem.IO, args arch.SyscallArguments) (uintptr, error) {
switch args[1].Int() {
case linux.FIONREAD:
diff --git a/pkg/shim/runsc/BUILD b/pkg/shim/runsc/BUILD
index 4d388ca05..f08599ebd 100644
--- a/pkg/shim/runsc/BUILD
+++ b/pkg/shim/runsc/BUILD
@@ -11,6 +11,6 @@ go_library(
visibility = ["//:sandbox"],
deps = [
"@com_github_containerd_go_runc//:go_default_library",
- "@com_github_opencontainers_runtime-spec//specs-go:go_default_library",
+ "@com_github_opencontainers_runtime_spec//specs-go:go_default_library",
],
)
diff --git a/pkg/shim/runsc/runsc.go b/pkg/shim/runsc/runsc.go
index 50807d0c5..c5cf68efa 100644
--- a/pkg/shim/runsc/runsc.go
+++ b/pkg/shim/runsc/runsc.go
@@ -1,5 +1,5 @@
// Copyright 2018 The containerd Authors.
-// Copyright 2018 The gVisor authors.
+// 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.
diff --git a/pkg/shim/runsc/utils.go b/pkg/shim/runsc/utils.go
index 2732d5e98..c514b3bc7 100644
--- a/pkg/shim/runsc/utils.go
+++ b/pkg/shim/runsc/utils.go
@@ -1,5 +1,5 @@
// Copyright 2018 The containerd Authors.
-// Copyright 2018 The gVisor authors.
+// 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.
diff --git a/pkg/shim/v1/proc/BUILD b/pkg/shim/v1/proc/BUILD
index a59bf198d..4377306af 100644
--- a/pkg/shim/v1/proc/BUILD
+++ b/pkg/shim/v1/proc/BUILD
@@ -25,11 +25,12 @@ go_library(
"@com_github_containerd_containerd//errdefs:go_default_library",
"@com_github_containerd_containerd//log:go_default_library",
"@com_github_containerd_containerd//mount:go_default_library",
- "@com_github_containerd_containerd//runtime/proc:go_default_library",
+ "@com_github_containerd_containerd//pkg/process:go_default_library",
+ "@com_github_containerd_containerd//pkg/stdio:go_default_library",
"@com_github_containerd_fifo//:go_default_library",
"@com_github_containerd_go_runc//:go_default_library",
"@com_github_gogo_protobuf//types:go_default_library",
- "@com_github_opencontainers_runtime-spec//specs-go:go_default_library",
+ "@com_github_opencontainers_runtime_spec//specs-go:go_default_library",
"@org_golang_x_sys//unix:go_default_library",
],
)
diff --git a/pkg/shim/v1/proc/deleted_state.go b/pkg/shim/v1/proc/deleted_state.go
index 52aad40ac..d9b970c4d 100644
--- a/pkg/shim/v1/proc/deleted_state.go
+++ b/pkg/shim/v1/proc/deleted_state.go
@@ -21,29 +21,29 @@ import (
"github.com/containerd/console"
"github.com/containerd/containerd/errdefs"
- "github.com/containerd/containerd/runtime/proc"
+ "github.com/containerd/containerd/pkg/process"
)
type deletedState struct{}
func (*deletedState) Resize(ws console.WinSize) error {
- return fmt.Errorf("cannot resize a deleted process")
+ return fmt.Errorf("cannot resize a deleted process.ss")
}
func (*deletedState) Start(ctx context.Context) error {
- return fmt.Errorf("cannot start a deleted process")
+ return fmt.Errorf("cannot start a deleted process.ss")
}
func (*deletedState) Delete(ctx context.Context) error {
- return fmt.Errorf("cannot delete a deleted process: %w", errdefs.ErrNotFound)
+ return fmt.Errorf("cannot delete a deleted process.ss: %w", errdefs.ErrNotFound)
}
func (*deletedState) Kill(ctx context.Context, sig uint32, all bool) error {
- return fmt.Errorf("cannot kill a deleted process: %w", errdefs.ErrNotFound)
+ return fmt.Errorf("cannot kill a deleted process.ss: %w", errdefs.ErrNotFound)
}
func (*deletedState) SetExited(status int) {}
-func (*deletedState) Exec(ctx context.Context, path string, r *ExecConfig) (proc.Process, error) {
+func (*deletedState) Exec(ctx context.Context, path string, r *ExecConfig) (process.Process, error) {
return nil, fmt.Errorf("cannot exec in a deleted state")
}
diff --git a/pkg/shim/v1/proc/exec.go b/pkg/shim/v1/proc/exec.go
index 4ef9cf6cf..1d1d90488 100644
--- a/pkg/shim/v1/proc/exec.go
+++ b/pkg/shim/v1/proc/exec.go
@@ -27,7 +27,7 @@ import (
"github.com/containerd/console"
"github.com/containerd/containerd/errdefs"
- "github.com/containerd/containerd/runtime/proc"
+ "github.com/containerd/containerd/pkg/stdio"
"github.com/containerd/fifo"
runc "github.com/containerd/go-runc"
specs "github.com/opencontainers/runtime-spec/specs-go"
@@ -51,7 +51,7 @@ type execProcess struct {
internalPid int
closers []io.Closer
stdin io.Closer
- stdio proc.Stdio
+ stdio stdio.Stdio
path string
spec specs.Process
@@ -164,7 +164,7 @@ func (e *execProcess) Stdin() io.Closer {
return e.stdin
}
-func (e *execProcess) Stdio() proc.Stdio {
+func (e *execProcess) Stdio() stdio.Stdio {
return e.stdio
}
@@ -223,7 +223,6 @@ func (e *execProcess) start(ctx context.Context) (err error) {
e.closers = append(e.closers, sc)
e.stdin = sc
}
- var copyWaitGroup sync.WaitGroup
ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
defer cancel()
if socket != nil {
@@ -231,15 +230,14 @@ func (e *execProcess) start(ctx context.Context) (err error) {
if err != nil {
return fmt.Errorf("failed to retrieve console master: %w", err)
}
- if e.console, err = e.parent.Platform.CopyConsole(ctx, console, e.stdio.Stdin, e.stdio.Stdout, e.stdio.Stderr, &e.wg, &copyWaitGroup); err != nil {
+ if e.console, err = e.parent.Platform.CopyConsole(ctx, console, e.stdio.Stdin, e.stdio.Stdout, e.stdio.Stderr, &e.wg); err != nil {
return fmt.Errorf("failed to start console copy: %w", err)
}
} else if !e.stdio.IsNull() {
- if err := copyPipes(ctx, e.io, e.stdio.Stdin, e.stdio.Stdout, e.stdio.Stderr, &e.wg, &copyWaitGroup); err != nil {
+ if err := copyPipes(ctx, e.io, e.stdio.Stdin, e.stdio.Stdout, e.stdio.Stderr, &e.wg); err != nil {
return fmt.Errorf("failed to start io pipe copy: %w", err)
}
}
- copyWaitGroup.Wait()
pid, err := runc.ReadPidFile(opts.PidFile)
if err != nil {
return fmt.Errorf("failed to retrieve OCI runtime exec pid: %w", err)
diff --git a/pkg/shim/v1/proc/init.go b/pkg/shim/v1/proc/init.go
index b429cb94f..dab3123d6 100644
--- a/pkg/shim/v1/proc/init.go
+++ b/pkg/shim/v1/proc/init.go
@@ -30,7 +30,8 @@ import (
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/log"
"github.com/containerd/containerd/mount"
- "github.com/containerd/containerd/runtime/proc"
+ "github.com/containerd/containerd/pkg/process"
+ "github.com/containerd/containerd/pkg/stdio"
"github.com/containerd/fifo"
runc "github.com/containerd/go-runc"
specs "github.com/opencontainers/runtime-spec/specs-go"
@@ -59,7 +60,7 @@ type Init struct {
id string
Bundle string
console console.Console
- Platform proc.Platform
+ Platform stdio.Platform
io runc.IO
runtime *runsc.Runsc
status int
@@ -67,7 +68,7 @@ type Init struct {
pid int
closers []io.Closer
stdin io.Closer
- stdio proc.Stdio
+ stdio stdio.Stdio
Rootfs string
IoUID int
IoGID int
@@ -92,7 +93,7 @@ func NewRunsc(root, path, namespace, runtime string, config map[string]string) *
}
// New returns a new init process.
-func New(id string, runtime *runsc.Runsc, stdio proc.Stdio) *Init {
+func New(id string, runtime *runsc.Runsc, stdio stdio.Stdio) *Init {
p := &Init{
id: id,
runtime: runtime,
@@ -144,7 +145,6 @@ func (p *Init) Create(ctx context.Context, r *CreateConfig) (err error) {
p.stdin = sc
p.closers = append(p.closers, sc)
}
- var copyWaitGroup sync.WaitGroup
ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
defer cancel()
if socket != nil {
@@ -152,18 +152,16 @@ func (p *Init) Create(ctx context.Context, r *CreateConfig) (err error) {
if err != nil {
return fmt.Errorf("failed to retrieve console master: %w", err)
}
- console, err = p.Platform.CopyConsole(ctx, console, r.Stdin, r.Stdout, r.Stderr, &p.wg, &copyWaitGroup)
+ console, err = p.Platform.CopyConsole(ctx, console, r.Stdin, r.Stdout, r.Stderr, &p.wg)
if err != nil {
return fmt.Errorf("failed to start console copy: %w", err)
}
p.console = console
} else if !hasNoIO(r) {
- if err := copyPipes(ctx, p.io, r.Stdin, r.Stdout, r.Stderr, &p.wg, &copyWaitGroup); err != nil {
+ if err := copyPipes(ctx, p.io, r.Stdin, r.Stdout, r.Stderr, &p.wg); err != nil {
return fmt.Errorf("failed to start io pipe copy: %w", err)
}
}
-
- copyWaitGroup.Wait()
pid, err := runc.ReadPidFile(pidFile)
if err != nil {
return fmt.Errorf("failed to retrieve OCI runtime container pid: %w", err)
@@ -391,7 +389,7 @@ func (p *Init) Runtime() *runsc.Runsc {
}
// Exec returns a new child process.
-func (p *Init) Exec(ctx context.Context, path string, r *ExecConfig) (proc.Process, error) {
+func (p *Init) Exec(ctx context.Context, path string, r *ExecConfig) (process.Process, error) {
p.mu.Lock()
defer p.mu.Unlock()
@@ -399,7 +397,7 @@ func (p *Init) Exec(ctx context.Context, path string, r *ExecConfig) (proc.Proce
}
// exec returns a new exec'd process.
-func (p *Init) exec(ctx context.Context, path string, r *ExecConfig) (proc.Process, error) {
+func (p *Init) exec(ctx context.Context, path string, r *ExecConfig) (process.Process, error) {
// process exec request
var spec specs.Process
if err := json.Unmarshal(r.Spec.Value, &spec); err != nil {
@@ -412,7 +410,7 @@ func (p *Init) exec(ctx context.Context, path string, r *ExecConfig) (proc.Proce
path: path,
parent: p,
spec: spec,
- stdio: proc.Stdio{
+ stdio: stdio.Stdio{
Stdin: r.Stdin,
Stdout: r.Stdout,
Stderr: r.Stderr,
@@ -425,7 +423,7 @@ func (p *Init) exec(ctx context.Context, path string, r *ExecConfig) (proc.Proce
}
// Stdio returns the stdio of the process.
-func (p *Init) Stdio() proc.Stdio {
+func (p *Init) Stdio() stdio.Stdio {
return p.stdio
}
@@ -453,7 +451,7 @@ func (p *Init) convertStatus(status string) string {
return status
}
-func withConditionalIO(c proc.Stdio) runc.IOOpt {
+func withConditionalIO(c stdio.Stdio) runc.IOOpt {
return func(o *runc.IOOption) {
o.OpenStdin = c.Stdin != ""
o.OpenStdout = c.Stdout != ""
diff --git a/pkg/shim/v1/proc/init_state.go b/pkg/shim/v1/proc/init_state.go
index 509f27762..9233ecc85 100644
--- a/pkg/shim/v1/proc/init_state.go
+++ b/pkg/shim/v1/proc/init_state.go
@@ -21,14 +21,14 @@ import (
"github.com/containerd/console"
"github.com/containerd/containerd/errdefs"
- "github.com/containerd/containerd/runtime/proc"
+ "github.com/containerd/containerd/pkg/process"
)
type initState interface {
Resize(console.WinSize) error
Start(context.Context) error
Delete(context.Context) error
- Exec(context.Context, string, *ExecConfig) (proc.Process, error)
+ Exec(context.Context, string, *ExecConfig) (process.Process, error)
Kill(context.Context, uint32, bool) error
SetExited(int)
}
@@ -94,7 +94,7 @@ func (s *createdState) SetExited(status int) {
}
}
-func (s *createdState) Exec(ctx context.Context, path string, r *ExecConfig) (proc.Process, error) {
+func (s *createdState) Exec(ctx context.Context, path string, r *ExecConfig) (process.Process, error) {
return s.p.exec(ctx, path, r)
}
@@ -117,11 +117,11 @@ func (s *runningState) Resize(ws console.WinSize) error {
}
func (s *runningState) Start(ctx context.Context) error {
- return fmt.Errorf("cannot start a running process")
+ return fmt.Errorf("cannot start a running process.ss")
}
func (s *runningState) Delete(ctx context.Context) error {
- return fmt.Errorf("cannot delete a running process")
+ return fmt.Errorf("cannot delete a running process.ss")
}
func (s *runningState) Kill(ctx context.Context, sig uint32, all bool) error {
@@ -136,7 +136,7 @@ func (s *runningState) SetExited(status int) {
}
}
-func (s *runningState) Exec(ctx context.Context, path string, r *ExecConfig) (proc.Process, error) {
+func (s *runningState) Exec(ctx context.Context, path string, r *ExecConfig) (process.Process, error) {
return s.p.exec(ctx, path, r)
}
@@ -159,7 +159,7 @@ func (s *stoppedState) Resize(ws console.WinSize) error {
}
func (s *stoppedState) Start(ctx context.Context) error {
- return fmt.Errorf("cannot start a stopped process")
+ return fmt.Errorf("cannot start a stopped process.ss")
}
func (s *stoppedState) Delete(ctx context.Context) error {
@@ -170,13 +170,13 @@ func (s *stoppedState) Delete(ctx context.Context) error {
}
func (s *stoppedState) Kill(ctx context.Context, sig uint32, all bool) error {
- return errdefs.ToGRPCf(errdefs.ErrNotFound, "process %s not found", s.p.id)
+ return errdefs.ToGRPCf(errdefs.ErrNotFound, "process.ss %s not found", s.p.id)
}
func (s *stoppedState) SetExited(status int) {
// no op
}
-func (s *stoppedState) Exec(ctx context.Context, path string, r *ExecConfig) (proc.Process, error) {
+func (s *stoppedState) Exec(ctx context.Context, path string, r *ExecConfig) (process.Process, error) {
return nil, fmt.Errorf("cannot exec in a stopped state")
}
diff --git a/pkg/shim/v1/proc/io.go b/pkg/shim/v1/proc/io.go
index 5313c7a50..34d825fb7 100644
--- a/pkg/shim/v1/proc/io.go
+++ b/pkg/shim/v1/proc/io.go
@@ -38,7 +38,7 @@ var bufPool = sync.Pool{
},
}
-func copyPipes(ctx context.Context, rio runc.IO, stdin, stdout, stderr string, wg, cwg *sync.WaitGroup) error {
+func copyPipes(ctx context.Context, rio runc.IO, stdin, stdout, stderr string, wg *sync.WaitGroup) error {
var sameFile *countingWriteCloser
for _, i := range []struct {
name string
@@ -48,9 +48,7 @@ func copyPipes(ctx context.Context, rio runc.IO, stdin, stdout, stderr string, w
name: stdout,
dest: func(wc io.WriteCloser, rc io.Closer) {
wg.Add(1)
- cwg.Add(1)
go func() {
- cwg.Done()
p := bufPool.Get().(*[]byte)
defer bufPool.Put(p)
if _, err := io.CopyBuffer(wc, rio.Stdout(), *p); err != nil {
@@ -67,9 +65,7 @@ func copyPipes(ctx context.Context, rio runc.IO, stdin, stdout, stderr string, w
name: stderr,
dest: func(wc io.WriteCloser, rc io.Closer) {
wg.Add(1)
- cwg.Add(1)
go func() {
- cwg.Done()
p := bufPool.Get().(*[]byte)
defer bufPool.Put(p)
if _, err := io.CopyBuffer(wc, rio.Stderr(), *p); err != nil {
@@ -124,9 +120,7 @@ func copyPipes(ctx context.Context, rio runc.IO, stdin, stdout, stderr string, w
if err != nil {
return fmt.Errorf("gvisor-containerd-shim: opening %s failed: %s", stdin, err)
}
- cwg.Add(1)
go func() {
- cwg.Done()
p := bufPool.Get().(*[]byte)
defer bufPool.Put(p)
diff --git a/pkg/shim/v1/proc/types.go b/pkg/shim/v1/proc/types.go
index 5c215de5f..2b0df4663 100644
--- a/pkg/shim/v1/proc/types.go
+++ b/pkg/shim/v1/proc/types.go
@@ -18,9 +18,8 @@ package proc
import (
"time"
- google_protobuf "github.com/gogo/protobuf/types"
-
runc "github.com/containerd/go-runc"
+ "github.com/gogo/protobuf/types"
)
// Mount holds filesystem mount configuration.
@@ -41,7 +40,7 @@ type CreateConfig struct {
Stdin string
Stdout string
Stderr string
- Options *google_protobuf.Any
+ Options *types.Any
}
// ExecConfig holds exec creation configuration.
@@ -51,7 +50,7 @@ type ExecConfig struct {
Stdin string
Stdout string
Stderr string
- Spec *google_protobuf.Any
+ Spec *types.Any
}
// Exit is the type of exit events.
diff --git a/pkg/shim/v1/shim/BUILD b/pkg/shim/v1/shim/BUILD
index 02cffbb01..05c595bc9 100644
--- a/pkg/shim/v1/shim/BUILD
+++ b/pkg/shim/v1/shim/BUILD
@@ -5,6 +5,7 @@ package(licenses = ["notice"])
go_library(
name = "shim",
srcs = [
+ "api.go",
"platform.go",
"service.go",
],
@@ -24,11 +25,12 @@ go_library(
"@com_github_containerd_containerd//log:go_default_library",
"@com_github_containerd_containerd//mount:go_default_library",
"@com_github_containerd_containerd//namespaces:go_default_library",
+ "@com_github_containerd_containerd//pkg/process:go_default_library",
+ "@com_github_containerd_containerd//pkg/stdio:go_default_library",
"@com_github_containerd_containerd//runtime:go_default_library",
"@com_github_containerd_containerd//runtime/linux/runctypes:go_default_library",
- "@com_github_containerd_containerd//runtime/proc:go_default_library",
- "@com_github_containerd_containerd//runtime/v1/shim:go_default_library",
"@com_github_containerd_containerd//runtime/v1/shim/v1:go_default_library",
+ "@com_github_containerd_containerd//sys/reaper:go_default_library",
"@com_github_containerd_fifo//:go_default_library",
"@com_github_containerd_typeurl//:go_default_library",
"@com_github_gogo_protobuf//types:go_default_library",
diff --git a/pkg/shim/v1/shim/api.go b/pkg/shim/v1/shim/api.go
new file mode 100644
index 000000000..5dd8ff172
--- /dev/null
+++ b/pkg/shim/v1/shim/api.go
@@ -0,0 +1,28 @@
+// Copyright 2018 The containerd Authors.
+// 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
+//
+// https://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 shim
+
+import (
+ "github.com/containerd/containerd/api/events"
+)
+
+type TaskCreate = events.TaskCreate
+type TaskStart = events.TaskStart
+type TaskOOM = events.TaskOOM
+type TaskExit = events.TaskExit
+type TaskDelete = events.TaskDelete
+type TaskExecAdded = events.TaskExecAdded
+type TaskExecStarted = events.TaskExecStarted
diff --git a/pkg/shim/v1/shim/platform.go b/pkg/shim/v1/shim/platform.go
index f6795563c..f590f80ef 100644
--- a/pkg/shim/v1/shim/platform.go
+++ b/pkg/shim/v1/shim/platform.go
@@ -30,7 +30,7 @@ type linuxPlatform struct {
epoller *console.Epoller
}
-func (p *linuxPlatform) CopyConsole(ctx context.Context, console console.Console, stdin, stdout, stderr string, wg, cwg *sync.WaitGroup) (console.Console, error) {
+func (p *linuxPlatform) CopyConsole(ctx context.Context, console console.Console, stdin, stdout, stderr string, wg *sync.WaitGroup) (console.Console, error) {
if p.epoller == nil {
return nil, fmt.Errorf("uninitialized epoller")
}
@@ -45,9 +45,7 @@ func (p *linuxPlatform) CopyConsole(ctx context.Context, console console.Console
if err != nil {
return nil, err
}
- cwg.Add(1)
go func() {
- cwg.Done()
p := bufPool.Get().(*[]byte)
defer bufPool.Put(p)
io.CopyBuffer(epollConsole, in, *p)
@@ -63,9 +61,7 @@ func (p *linuxPlatform) CopyConsole(ctx context.Context, console console.Console
return nil, err
}
wg.Add(1)
- cwg.Add(1)
go func() {
- cwg.Done()
p := bufPool.Get().(*[]byte)
defer bufPool.Put(p)
io.CopyBuffer(outw, epollConsole, *p)
diff --git a/pkg/shim/v1/shim/service.go b/pkg/shim/v1/shim/service.go
index 7b0280ed2..84a810cb2 100644
--- a/pkg/shim/v1/shim/service.go
+++ b/pkg/shim/v1/shim/service.go
@@ -23,20 +23,20 @@ import (
"sync"
"github.com/containerd/console"
- eventstypes "github.com/containerd/containerd/api/events"
"github.com/containerd/containerd/api/types/task"
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/events"
"github.com/containerd/containerd/log"
"github.com/containerd/containerd/mount"
"github.com/containerd/containerd/namespaces"
+ "github.com/containerd/containerd/pkg/process"
+ "github.com/containerd/containerd/pkg/stdio"
"github.com/containerd/containerd/runtime"
"github.com/containerd/containerd/runtime/linux/runctypes"
- rproc "github.com/containerd/containerd/runtime/proc"
- "github.com/containerd/containerd/runtime/v1/shim"
- shimapi "github.com/containerd/containerd/runtime/v1/shim/v1"
+ shim "github.com/containerd/containerd/runtime/v1/shim/v1"
+ "github.com/containerd/containerd/sys/reaper"
"github.com/containerd/typeurl"
- ptypes "github.com/gogo/protobuf/types"
+ "github.com/gogo/protobuf/types"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
@@ -46,7 +46,7 @@ import (
)
var (
- empty = &ptypes.Empty{}
+ empty = &types.Empty{}
bufPool = sync.Pool{
New: func() interface{} {
buffer := make([]byte, 32<<10)
@@ -73,7 +73,7 @@ func NewService(config Config, publisher events.Publisher) (*Service, error) {
s := &Service{
config: config,
context: ctx,
- processes: make(map[string]rproc.Process),
+ processes: make(map[string]process.Process),
events: make(chan interface{}, 128),
ec: proc.ExitCh,
}
@@ -91,9 +91,9 @@ type Service struct {
config Config
context context.Context
- processes map[string]rproc.Process
+ processes map[string]process.Process
events chan interface{}
- platform rproc.Platform
+ platform stdio.Platform
ec chan proc.Exit
// Filled by Create()
@@ -102,7 +102,7 @@ type Service struct {
}
// Create creates a new initial process and container with the underlying OCI runtime.
-func (s *Service) Create(ctx context.Context, r *shimapi.CreateTaskRequest) (_ *shimapi.CreateTaskResponse, err error) {
+func (s *Service) Create(ctx context.Context, r *shim.CreateTaskRequest) (_ *shim.CreateTaskResponse, err error) {
s.mu.Lock()
defer s.mu.Unlock()
@@ -168,13 +168,13 @@ func (s *Service) Create(ctx context.Context, r *shimapi.CreateTaskRequest) (_ *
s.bundle = r.Bundle
pid := process.Pid()
s.processes[r.ID] = process
- return &shimapi.CreateTaskResponse{
+ return &shim.CreateTaskResponse{
Pid: uint32(pid),
}, nil
}
// Start starts a process.
-func (s *Service) Start(ctx context.Context, r *shimapi.StartRequest) (*shimapi.StartResponse, error) {
+func (s *Service) Start(ctx context.Context, r *shim.StartRequest) (*shim.StartResponse, error) {
p, err := s.getExecProcess(r.ID)
if err != nil {
return nil, err
@@ -182,14 +182,14 @@ func (s *Service) Start(ctx context.Context, r *shimapi.StartRequest) (*shimapi.
if err := p.Start(ctx); err != nil {
return nil, err
}
- return &shimapi.StartResponse{
+ return &shim.StartResponse{
ID: p.ID(),
Pid: uint32(p.Pid()),
}, nil
}
// Delete deletes the initial process and container.
-func (s *Service) Delete(ctx context.Context, r *ptypes.Empty) (*shimapi.DeleteResponse, error) {
+func (s *Service) Delete(ctx context.Context, r *types.Empty) (*shim.DeleteResponse, error) {
p, err := s.getInitProcess()
if err != nil {
return nil, err
@@ -201,7 +201,7 @@ func (s *Service) Delete(ctx context.Context, r *ptypes.Empty) (*shimapi.DeleteR
delete(s.processes, s.id)
s.mu.Unlock()
s.platform.Close()
- return &shimapi.DeleteResponse{
+ return &shim.DeleteResponse{
ExitStatus: uint32(p.ExitStatus()),
ExitedAt: p.ExitedAt(),
Pid: uint32(p.Pid()),
@@ -209,7 +209,7 @@ func (s *Service) Delete(ctx context.Context, r *ptypes.Empty) (*shimapi.DeleteR
}
// DeleteProcess deletes an exec'd process.
-func (s *Service) DeleteProcess(ctx context.Context, r *shimapi.DeleteProcessRequest) (*shimapi.DeleteResponse, error) {
+func (s *Service) DeleteProcess(ctx context.Context, r *shim.DeleteProcessRequest) (*shim.DeleteResponse, error) {
if r.ID == s.id {
return nil, status.Errorf(codes.InvalidArgument, "cannot delete init process with DeleteProcess")
}
@@ -223,7 +223,7 @@ func (s *Service) DeleteProcess(ctx context.Context, r *shimapi.DeleteProcessReq
s.mu.Lock()
delete(s.processes, r.ID)
s.mu.Unlock()
- return &shimapi.DeleteResponse{
+ return &shim.DeleteResponse{
ExitStatus: uint32(p.ExitStatus()),
ExitedAt: p.ExitedAt(),
Pid: uint32(p.Pid()),
@@ -231,7 +231,7 @@ func (s *Service) DeleteProcess(ctx context.Context, r *shimapi.DeleteProcessReq
}
// Exec spawns an additional process inside the container.
-func (s *Service) Exec(ctx context.Context, r *shimapi.ExecProcessRequest) (*ptypes.Empty, error) {
+func (s *Service) Exec(ctx context.Context, r *shim.ExecProcessRequest) (*types.Empty, error) {
s.mu.Lock()
if p := s.processes[r.ID]; p != nil {
@@ -263,7 +263,7 @@ func (s *Service) Exec(ctx context.Context, r *shimapi.ExecProcessRequest) (*pty
}
// ResizePty resises the terminal of a process.
-func (s *Service) ResizePty(ctx context.Context, r *shimapi.ResizePtyRequest) (*ptypes.Empty, error) {
+func (s *Service) ResizePty(ctx context.Context, r *shim.ResizePtyRequest) (*types.Empty, error) {
if r.ID == "" {
return nil, errdefs.ToGRPCf(errdefs.ErrInvalidArgument, "id not provided")
}
@@ -282,7 +282,7 @@ func (s *Service) ResizePty(ctx context.Context, r *shimapi.ResizePtyRequest) (*
}
// State returns runtime state information for a process.
-func (s *Service) State(ctx context.Context, r *shimapi.StateRequest) (*shimapi.StateResponse, error) {
+func (s *Service) State(ctx context.Context, r *shim.StateRequest) (*shim.StateResponse, error) {
p, err := s.getExecProcess(r.ID)
if err != nil {
return nil, err
@@ -301,7 +301,7 @@ func (s *Service) State(ctx context.Context, r *shimapi.StateRequest) (*shimapi.
status = task.StatusStopped
}
sio := p.Stdio()
- return &shimapi.StateResponse{
+ return &shim.StateResponse{
ID: p.ID(),
Bundle: s.bundle,
Pid: uint32(p.Pid()),
@@ -316,17 +316,17 @@ func (s *Service) State(ctx context.Context, r *shimapi.StateRequest) (*shimapi.
}
// Pause pauses the container.
-func (s *Service) Pause(ctx context.Context, r *ptypes.Empty) (*ptypes.Empty, error) {
+func (s *Service) Pause(ctx context.Context, r *types.Empty) (*types.Empty, error) {
return empty, errdefs.ToGRPC(errdefs.ErrNotImplemented)
}
// Resume resumes the container.
-func (s *Service) Resume(ctx context.Context, r *ptypes.Empty) (*ptypes.Empty, error) {
+func (s *Service) Resume(ctx context.Context, r *types.Empty) (*types.Empty, error) {
return empty, errdefs.ToGRPC(errdefs.ErrNotImplemented)
}
// Kill kills a process with the provided signal.
-func (s *Service) Kill(ctx context.Context, r *shimapi.KillRequest) (*ptypes.Empty, error) {
+func (s *Service) Kill(ctx context.Context, r *shim.KillRequest) (*types.Empty, error) {
if r.ID == "" {
p, err := s.getInitProcess()
if err != nil {
@@ -349,7 +349,7 @@ func (s *Service) Kill(ctx context.Context, r *shimapi.KillRequest) (*ptypes.Emp
}
// ListPids returns all pids inside the container.
-func (s *Service) ListPids(ctx context.Context, r *shimapi.ListPidsRequest) (*shimapi.ListPidsResponse, error) {
+func (s *Service) ListPids(ctx context.Context, r *shim.ListPidsRequest) (*shim.ListPidsResponse, error) {
pids, err := s.getContainerPids(ctx, r.ID)
if err != nil {
return nil, errdefs.ToGRPC(err)
@@ -374,13 +374,13 @@ func (s *Service) ListPids(ctx context.Context, r *shimapi.ListPidsRequest) (*sh
}
processes = append(processes, &pInfo)
}
- return &shimapi.ListPidsResponse{
+ return &shim.ListPidsResponse{
Processes: processes,
}, nil
}
// CloseIO closes the I/O context of a process.
-func (s *Service) CloseIO(ctx context.Context, r *shimapi.CloseIORequest) (*ptypes.Empty, error) {
+func (s *Service) CloseIO(ctx context.Context, r *shim.CloseIORequest) (*types.Empty, error) {
p, err := s.getExecProcess(r.ID)
if err != nil {
return nil, err
@@ -394,31 +394,31 @@ func (s *Service) CloseIO(ctx context.Context, r *shimapi.CloseIORequest) (*ptyp
}
// Checkpoint checkpoints the container.
-func (s *Service) Checkpoint(ctx context.Context, r *shimapi.CheckpointTaskRequest) (*ptypes.Empty, error) {
+func (s *Service) Checkpoint(ctx context.Context, r *shim.CheckpointTaskRequest) (*types.Empty, error) {
return empty, errdefs.ToGRPC(errdefs.ErrNotImplemented)
}
// ShimInfo returns shim information such as the shim's pid.
-func (s *Service) ShimInfo(ctx context.Context, r *ptypes.Empty) (*shimapi.ShimInfoResponse, error) {
- return &shimapi.ShimInfoResponse{
+func (s *Service) ShimInfo(ctx context.Context, r *types.Empty) (*shim.ShimInfoResponse, error) {
+ return &shim.ShimInfoResponse{
ShimPid: uint32(os.Getpid()),
}, nil
}
// Update updates a running container.
-func (s *Service) Update(ctx context.Context, r *shimapi.UpdateTaskRequest) (*ptypes.Empty, error) {
+func (s *Service) Update(ctx context.Context, r *shim.UpdateTaskRequest) (*types.Empty, error) {
return empty, errdefs.ToGRPC(errdefs.ErrNotImplemented)
}
// Wait waits for a process to exit.
-func (s *Service) Wait(ctx context.Context, r *shimapi.WaitRequest) (*shimapi.WaitResponse, error) {
+func (s *Service) Wait(ctx context.Context, r *shim.WaitRequest) (*shim.WaitResponse, error) {
p, err := s.getExecProcess(r.ID)
if err != nil {
return nil, err
}
p.Wait()
- return &shimapi.WaitResponse{
+ return &shim.WaitResponse{
ExitStatus: uint32(p.ExitStatus()),
ExitedAt: p.ExitedAt(),
}, nil
@@ -430,11 +430,11 @@ func (s *Service) processExits() {
}
}
-func (s *Service) allProcesses() []rproc.Process {
+func (s *Service) allProcesses() []process.Process {
s.mu.Lock()
defer s.mu.Unlock()
- res := make([]rproc.Process, 0, len(s.processes))
+ res := make([]process.Process, 0, len(s.processes))
for _, p := range s.processes {
res = append(res, p)
}
@@ -452,7 +452,7 @@ func (s *Service) checkProcesses(e proc.Exit) {
}
}
p.SetExited(e.Status)
- s.events <- &eventstypes.TaskExit{
+ s.events <- &TaskExit{
ContainerID: s.id,
ID: p.ID(),
Pid: uint32(p.Pid()),
@@ -490,7 +490,7 @@ func (s *Service) forward(publisher events.Publisher) {
}
// getInitProcess returns the init process.
-func (s *Service) getInitProcess() (rproc.Process, error) {
+func (s *Service) getInitProcess() (process.Process, error) {
s.mu.Lock()
defer s.mu.Unlock()
p := s.processes[s.id]
@@ -501,7 +501,7 @@ func (s *Service) getInitProcess() (rproc.Process, error) {
}
// getExecProcess returns the given exec process.
-func (s *Service) getExecProcess(id string) (rproc.Process, error) {
+func (s *Service) getExecProcess(id string) (process.Process, error) {
s.mu.Lock()
defer s.mu.Unlock()
p := s.processes[id]
@@ -513,19 +513,19 @@ func (s *Service) getExecProcess(id string) (rproc.Process, error) {
func getTopic(ctx context.Context, e interface{}) string {
switch e.(type) {
- case *eventstypes.TaskCreate:
+ case *TaskCreate:
return runtime.TaskCreateEventTopic
- case *eventstypes.TaskStart:
+ case *TaskStart:
return runtime.TaskStartEventTopic
- case *eventstypes.TaskOOM:
+ case *TaskOOM:
return runtime.TaskOOMEventTopic
- case *eventstypes.TaskExit:
+ case *TaskExit:
return runtime.TaskExitEventTopic
- case *eventstypes.TaskDelete:
+ case *TaskDelete:
return runtime.TaskDeleteEventTopic
- case *eventstypes.TaskExecAdded:
+ case *TaskExecAdded:
return runtime.TaskExecAddedEventTopic
- case *eventstypes.TaskExecStarted:
+ case *TaskExecStarted:
return runtime.TaskExecStartedEventTopic
default:
log.L.Printf("no topic for type %#v", e)
@@ -533,7 +533,7 @@ func getTopic(ctx context.Context, e interface{}) string {
return runtime.TaskUnknownTopic
}
-func newInit(ctx context.Context, path, workDir, runtimeRoot, namespace string, config map[string]string, platform rproc.Platform, r *proc.CreateConfig) (*proc.Init, error) {
+func newInit(ctx context.Context, path, workDir, runtimeRoot, namespace string, config map[string]string, platform stdio.Platform, r *proc.CreateConfig) (*proc.Init, error) {
var options runctypes.CreateOptions
if r.Options != nil {
v, err := typeurl.UnmarshalAny(r.Options)
@@ -554,7 +554,7 @@ func newInit(ctx context.Context, path, workDir, runtimeRoot, namespace string,
runsc.FormatLogPath(r.ID, config)
rootfs := filepath.Join(path, "rootfs")
runtime := proc.NewRunsc(runtimeRoot, path, namespace, r.Runtime, config)
- p := proc.New(r.ID, runtime, rproc.Stdio{
+ p := proc.New(r.ID, runtime, stdio.Stdio{
Stdin: r.Stdin,
Stdout: r.Stdout,
Stderr: r.Stderr,
@@ -568,6 +568,6 @@ func newInit(ctx context.Context, path, workDir, runtimeRoot, namespace string,
p.IoGID = int(options.IoGid)
p.Sandbox = utils.IsSandbox(spec)
p.UserLog = utils.UserLogPath(spec)
- p.Monitor = shim.Default
+ p.Monitor = reaper.Default
return p, nil
}
diff --git a/pkg/shim/v1/utils/BUILD b/pkg/shim/v1/utils/BUILD
index 9045781e1..54a0aabb7 100644
--- a/pkg/shim/v1/utils/BUILD
+++ b/pkg/shim/v1/utils/BUILD
@@ -5,6 +5,7 @@ package(licenses = ["notice"])
go_library(
name = "utils",
srcs = [
+ "annotations.go",
"utils.go",
"volumes.go",
],
@@ -13,8 +14,7 @@ go_library(
"//shim:__subpackages__",
],
deps = [
- "@com_github_containerd_cri//pkg/annotations:go_default_library",
- "@com_github_opencontainers_runtime-spec//specs-go:go_default_library",
+ "@com_github_opencontainers_runtime_spec//specs-go:go_default_library",
],
)
@@ -23,4 +23,5 @@ go_test(
size = "small",
srcs = ["volumes_test.go"],
library = ":utils",
+ deps = ["@com_github_opencontainers_runtime_spec//specs-go:go_default_library"],
)
diff --git a/pkg/shim/v1/utils/annotations.go b/pkg/shim/v1/utils/annotations.go
new file mode 100644
index 000000000..1e9d3f365
--- /dev/null
+++ b/pkg/shim/v1/utils/annotations.go
@@ -0,0 +1,25 @@
+// 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
+//
+// https://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 utils
+
+// Annotations from the CRI annotations package.
+//
+// These are vendor due to import conflicts.
+const (
+ sandboxLogDirAnnotation = "io.kubernetes.cri.sandbox-log-directory"
+ containerTypeAnnotation = "io.kubernetes.cri.container-type"
+ containerTypeSandbox = "sandbox"
+ containerTypeContainer = "container"
+)
diff --git a/pkg/shim/v1/utils/utils.go b/pkg/shim/v1/utils/utils.go
index 7a400af1c..07e346654 100644
--- a/pkg/shim/v1/utils/utils.go
+++ b/pkg/shim/v1/utils/utils.go
@@ -20,7 +20,6 @@ import (
"os"
"path/filepath"
- "github.com/containerd/cri/pkg/annotations"
specs "github.com/opencontainers/runtime-spec/specs-go"
)
@@ -43,13 +42,13 @@ func ReadSpec(bundle string) (*specs.Spec, error) {
// IsSandbox checks whether a container is a sandbox container.
func IsSandbox(spec *specs.Spec) bool {
- t, ok := spec.Annotations[annotations.ContainerType]
- return !ok || t == annotations.ContainerTypeSandbox
+ t, ok := spec.Annotations[containerTypeAnnotation]
+ return !ok || t == containerTypeSandbox
}
// UserLogPath gets user log path from OCI annotation.
func UserLogPath(spec *specs.Spec) string {
- sandboxLogDir := spec.Annotations[annotations.SandboxLogDir]
+ sandboxLogDir := spec.Annotations[sandboxLogDirAnnotation]
if sandboxLogDir == "" {
return ""
}
diff --git a/pkg/shim/v1/utils/volumes.go b/pkg/shim/v1/utils/volumes.go
index e4e9bf9b1..52a428179 100644
--- a/pkg/shim/v1/utils/volumes.go
+++ b/pkg/shim/v1/utils/volumes.go
@@ -21,7 +21,6 @@ import (
"path/filepath"
"strings"
- "github.com/containerd/cri/pkg/annotations"
specs "github.com/opencontainers/runtime-spec/specs-go"
)
@@ -44,7 +43,7 @@ func volumeFieldName(k string) string {
// podUID gets pod UID from the pod log path.
func podUID(s *specs.Spec) (string, error) {
- sandboxLogDir := s.Annotations[annotations.SandboxLogDir]
+ sandboxLogDir := s.Annotations[sandboxLogDirAnnotation]
if sandboxLogDir == "" {
return "", fmt.Errorf("no sandbox log path annotation")
}
@@ -101,7 +100,6 @@ func UpdateVolumeAnnotations(bundle string, s *specs.Spec) error {
if err != nil {
// Skip if we can't get pod UID, because this doesn't work
// for containerd 1.1.
- fmt.Errorf("Can't get pod uid: %w", err)
return nil
}
}
diff --git a/pkg/shim/v1/utils/volumes_test.go b/pkg/shim/v1/utils/volumes_test.go
index 4b2639545..3e02c6151 100644
--- a/pkg/shim/v1/utils/volumes_test.go
+++ b/pkg/shim/v1/utils/volumes_test.go
@@ -23,7 +23,6 @@ import (
"reflect"
"testing"
- "github.com/containerd/cri/pkg/annotations"
specs "github.com/opencontainers/runtime-spec/specs-go"
)
@@ -58,8 +57,8 @@ func TestUpdateVolumeAnnotations(t *testing.T) {
desc: "volume annotations for sandbox",
spec: &specs.Spec{
Annotations: map[string]string{
- annotations.SandboxLogDir: testLogDirPath,
- annotations.ContainerType: annotations.ContainerTypeSandbox,
+ sandboxLogDirAnnotation: testLogDirPath,
+ containerTypeAnnotation: containerTypeSandbox,
"dev.gvisor.spec.mount." + testVolumeName + ".share": "pod",
"dev.gvisor.spec.mount." + testVolumeName + ".type": "tmpfs",
"dev.gvisor.spec.mount." + testVolumeName + ".options": "ro",
@@ -67,8 +66,8 @@ func TestUpdateVolumeAnnotations(t *testing.T) {
},
expected: &specs.Spec{
Annotations: map[string]string{
- annotations.SandboxLogDir: testLogDirPath,
- annotations.ContainerType: annotations.ContainerTypeSandbox,
+ sandboxLogDirAnnotation: testLogDirPath,
+ containerTypeAnnotation: containerTypeSandbox,
"dev.gvisor.spec.mount." + testVolumeName + ".share": "pod",
"dev.gvisor.spec.mount." + testVolumeName + ".type": "tmpfs",
"dev.gvisor.spec.mount." + testVolumeName + ".options": "ro",
@@ -81,8 +80,8 @@ func TestUpdateVolumeAnnotations(t *testing.T) {
desc: "volume annotations for sandbox with legacy log path",
spec: &specs.Spec{
Annotations: map[string]string{
- annotations.SandboxLogDir: testLegacyLogDirPath,
- annotations.ContainerType: annotations.ContainerTypeSandbox,
+ sandboxLogDirAnnotation: testLegacyLogDirPath,
+ containerTypeAnnotation: containerTypeSandbox,
"dev.gvisor.spec.mount." + testVolumeName + ".share": "pod",
"dev.gvisor.spec.mount." + testVolumeName + ".type": "tmpfs",
"dev.gvisor.spec.mount." + testVolumeName + ".options": "ro",
@@ -90,8 +89,8 @@ func TestUpdateVolumeAnnotations(t *testing.T) {
},
expected: &specs.Spec{
Annotations: map[string]string{
- annotations.SandboxLogDir: testLegacyLogDirPath,
- annotations.ContainerType: annotations.ContainerTypeSandbox,
+ sandboxLogDirAnnotation: testLegacyLogDirPath,
+ containerTypeAnnotation: containerTypeSandbox,
"dev.gvisor.spec.mount." + testVolumeName + ".share": "pod",
"dev.gvisor.spec.mount." + testVolumeName + ".type": "tmpfs",
"dev.gvisor.spec.mount." + testVolumeName + ".options": "ro",
@@ -118,7 +117,7 @@ func TestUpdateVolumeAnnotations(t *testing.T) {
},
},
Annotations: map[string]string{
- annotations.ContainerType: annotations.ContainerTypeContainer,
+ containerTypeAnnotation: containerTypeContainer,
"dev.gvisor.spec.mount." + testVolumeName + ".share": "pod",
"dev.gvisor.spec.mount." + testVolumeName + ".type": "tmpfs",
"dev.gvisor.spec.mount." + testVolumeName + ".options": "ro",
@@ -140,7 +139,7 @@ func TestUpdateVolumeAnnotations(t *testing.T) {
},
},
Annotations: map[string]string{
- annotations.ContainerType: annotations.ContainerTypeContainer,
+ containerTypeAnnotation: containerTypeContainer,
"dev.gvisor.spec.mount." + testVolumeName + ".share": "pod",
"dev.gvisor.spec.mount." + testVolumeName + ".type": "tmpfs",
"dev.gvisor.spec.mount." + testVolumeName + ".options": "ro",
@@ -160,7 +159,7 @@ func TestUpdateVolumeAnnotations(t *testing.T) {
},
},
Annotations: map[string]string{
- annotations.ContainerType: annotations.ContainerTypeContainer,
+ containerTypeAnnotation: containerTypeContainer,
"dev.gvisor.spec.mount." + testVolumeName + ".share": "container",
"dev.gvisor.spec.mount." + testVolumeName + ".type": "bind",
"dev.gvisor.spec.mount." + testVolumeName + ".options": "ro",
@@ -176,7 +175,7 @@ func TestUpdateVolumeAnnotations(t *testing.T) {
},
},
Annotations: map[string]string{
- annotations.ContainerType: annotations.ContainerTypeContainer,
+ containerTypeAnnotation: containerTypeContainer,
"dev.gvisor.spec.mount." + testVolumeName + ".share": "container",
"dev.gvisor.spec.mount." + testVolumeName + ".type": "bind",
"dev.gvisor.spec.mount." + testVolumeName + ".options": "ro",
@@ -188,7 +187,7 @@ func TestUpdateVolumeAnnotations(t *testing.T) {
desc: "should not return error without pod log directory",
spec: &specs.Spec{
Annotations: map[string]string{
- annotations.ContainerType: annotations.ContainerTypeSandbox,
+ containerTypeAnnotation: containerTypeSandbox,
"dev.gvisor.spec.mount." + testVolumeName + ".share": "pod",
"dev.gvisor.spec.mount." + testVolumeName + ".type": "tmpfs",
"dev.gvisor.spec.mount." + testVolumeName + ".options": "ro",
@@ -196,7 +195,7 @@ func TestUpdateVolumeAnnotations(t *testing.T) {
},
expected: &specs.Spec{
Annotations: map[string]string{
- annotations.ContainerType: annotations.ContainerTypeSandbox,
+ containerTypeAnnotation: containerTypeSandbox,
"dev.gvisor.spec.mount." + testVolumeName + ".share": "pod",
"dev.gvisor.spec.mount." + testVolumeName + ".type": "tmpfs",
"dev.gvisor.spec.mount." + testVolumeName + ".options": "ro",
@@ -207,8 +206,8 @@ func TestUpdateVolumeAnnotations(t *testing.T) {
desc: "should return error if volume path does not exist",
spec: &specs.Spec{
Annotations: map[string]string{
- annotations.SandboxLogDir: testLogDirPath,
- annotations.ContainerType: annotations.ContainerTypeSandbox,
+ sandboxLogDirAnnotation: testLogDirPath,
+ containerTypeAnnotation: containerTypeSandbox,
"dev.gvisor.spec.mount.notexist.share": "pod",
"dev.gvisor.spec.mount.notexist.type": "tmpfs",
"dev.gvisor.spec.mount.notexist.options": "ro",
@@ -220,14 +219,14 @@ func TestUpdateVolumeAnnotations(t *testing.T) {
desc: "no volume annotations for sandbox",
spec: &specs.Spec{
Annotations: map[string]string{
- annotations.SandboxLogDir: testLogDirPath,
- annotations.ContainerType: annotations.ContainerTypeSandbox,
+ sandboxLogDirAnnotation: testLogDirPath,
+ containerTypeAnnotation: containerTypeSandbox,
},
},
expected: &specs.Spec{
Annotations: map[string]string{
- annotations.SandboxLogDir: testLogDirPath,
- annotations.ContainerType: annotations.ContainerTypeSandbox,
+ sandboxLogDirAnnotation: testLogDirPath,
+ containerTypeAnnotation: containerTypeSandbox,
},
},
},
@@ -249,7 +248,7 @@ func TestUpdateVolumeAnnotations(t *testing.T) {
},
},
Annotations: map[string]string{
- annotations.ContainerType: annotations.ContainerTypeContainer,
+ containerTypeAnnotation: containerTypeContainer,
},
},
expected: &specs.Spec{
@@ -268,7 +267,7 @@ func TestUpdateVolumeAnnotations(t *testing.T) {
},
},
Annotations: map[string]string{
- annotations.ContainerType: annotations.ContainerTypeContainer,
+ containerTypeAnnotation: containerTypeContainer,
},
},
},
diff --git a/pkg/shim/v2/BUILD b/pkg/shim/v2/BUILD
index 450f62979..7e0a114a0 100644
--- a/pkg/shim/v2/BUILD
+++ b/pkg/shim/v2/BUILD
@@ -5,6 +5,7 @@ package(licenses = ["notice"])
go_library(
name = "v2",
srcs = [
+ "api.go",
"epoll.go",
"service.go",
"service_linux.go",
@@ -15,10 +16,10 @@ go_library(
"//pkg/shim/v1/proc",
"//pkg/shim/v1/utils",
"//pkg/shim/v2/options",
+ "//pkg/shim/v2/runtimeoptions",
"//runsc/specutils",
"@com_github_burntsushi_toml//:go_default_library",
"@com_github_containerd_cgroups//:go_default_library",
- "@com_github_containerd_cgroups//stats/v1:go_default_library",
"@com_github_containerd_console//:go_default_library",
"@com_github_containerd_containerd//api/events:go_default_library",
"@com_github_containerd_containerd//api/types/task:go_default_library",
@@ -27,12 +28,13 @@ go_library(
"@com_github_containerd_containerd//log:go_default_library",
"@com_github_containerd_containerd//mount:go_default_library",
"@com_github_containerd_containerd//namespaces:go_default_library",
+ "@com_github_containerd_containerd//pkg/process:go_default_library",
+ "@com_github_containerd_containerd//pkg/stdio:go_default_library",
"@com_github_containerd_containerd//runtime:go_default_library",
"@com_github_containerd_containerd//runtime/linux/runctypes:go_default_library",
- "@com_github_containerd_containerd//runtime/proc:go_default_library",
"@com_github_containerd_containerd//runtime/v2/shim:go_default_library",
"@com_github_containerd_containerd//runtime/v2/task:go_default_library",
- "@com_github_containerd_cri//pkg/api/runtimeoptions/v1:go_default_library",
+ "@com_github_containerd_containerd//sys/reaper:go_default_library",
"@com_github_containerd_fifo//:go_default_library",
"@com_github_containerd_typeurl//:go_default_library",
"@com_github_gogo_protobuf//types:go_default_library",
diff --git a/pkg/shim/v2/api.go b/pkg/shim/v2/api.go
new file mode 100644
index 000000000..dbe5c59f6
--- /dev/null
+++ b/pkg/shim/v2/api.go
@@ -0,0 +1,22 @@
+// Copyright 2018 The containerd Authors.
+// 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
+//
+// https://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 v2
+
+import (
+ "github.com/containerd/containerd/api/events"
+)
+
+type TaskOOM = events.TaskOOM
diff --git a/pkg/shim/v2/epoll.go b/pkg/shim/v2/epoll.go
index 45cc38c2a..41232cca8 100644
--- a/pkg/shim/v2/epoll.go
+++ b/pkg/shim/v2/epoll.go
@@ -23,7 +23,6 @@ import (
"sync"
"github.com/containerd/cgroups"
- eventstypes "github.com/containerd/containerd/api/events"
"github.com/containerd/containerd/events"
"github.com/containerd/containerd/runtime"
"golang.org/x/sys/unix"
@@ -68,10 +67,11 @@ func (e *epoller) run(ctx context.Context) {
default:
n, err := unix.EpollWait(e.fd, events[:], -1)
if err != nil {
- if err == unix.EINTR {
+ if err == unix.EINTR || err == unix.EAGAIN {
continue
}
- fmt.Errorf("cgroups: epoll wait: %w", err)
+ // Should not happen.
+ panic(fmt.Errorf("cgroups: epoll wait: %w", err))
}
for i := 0; i < n; i++ {
e.process(ctx, uintptr(events[i].Fd))
@@ -114,10 +114,11 @@ func (e *epoller) process(ctx context.Context, fd uintptr) {
unix.Close(int(fd))
return
}
- if err := e.publisher.Publish(ctx, runtime.TaskOOMEventTopic, &eventstypes.TaskOOM{
+ if err := e.publisher.Publish(ctx, runtime.TaskOOMEventTopic, &TaskOOM{
ContainerID: i.id,
}); err != nil {
- fmt.Errorf("publish OOM event: %w", err)
+ // Should not happen.
+ panic(fmt.Errorf("publish OOM event: %w", err))
}
}
diff --git a/pkg/shim/v2/runtimeoptions/BUILD b/pkg/shim/v2/runtimeoptions/BUILD
new file mode 100644
index 000000000..01716034c
--- /dev/null
+++ b/pkg/shim/v2/runtimeoptions/BUILD
@@ -0,0 +1,20 @@
+load("//tools:defs.bzl", "go_library", "proto_library")
+
+package(licenses = ["notice"])
+
+proto_library(
+ name = "api",
+ srcs = [
+ "runtimeoptions.proto",
+ ],
+)
+
+go_library(
+ name = "runtimeoptions",
+ srcs = ["runtimeoptions.go"],
+ visibility = ["//pkg/shim/v2:__pkg__"],
+ deps = [
+ "//pkg/shim/v2/runtimeoptions:api_go_proto",
+ "@com_github_gogo_protobuf//proto:go_default_library",
+ ],
+)
diff --git a/pkg/shim/v2/runtimeoptions/runtimeoptions.go b/pkg/shim/v2/runtimeoptions/runtimeoptions.go
new file mode 100644
index 000000000..1c1a0c5d1
--- /dev/null
+++ b/pkg/shim/v2/runtimeoptions/runtimeoptions.go
@@ -0,0 +1,27 @@
+// Copyright 2018 The containerd Authors.
+// 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
+//
+// https://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 runtimeoptions
+
+import (
+ proto "github.com/gogo/protobuf/proto"
+ pb "gvisor.dev/gvisor/pkg/shim/v2/runtimeoptions/api_go_proto"
+)
+
+type Options = pb.Options
+
+func init() {
+ proto.RegisterType((*Options)(nil), "cri.runtimeoptions.v1.Options")
+}
diff --git a/pkg/shim/v2/runtimeoptions/runtimeoptions.proto b/pkg/shim/v2/runtimeoptions/runtimeoptions.proto
new file mode 100644
index 000000000..edb19020a
--- /dev/null
+++ b/pkg/shim/v2/runtimeoptions/runtimeoptions.proto
@@ -0,0 +1,25 @@
+// Copyright 2020 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
+//
+// https://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.
+
+syntax = "proto3";
+
+package runtimeoptions;
+
+// This is a version of the runtimeoptions CRI API that is vendored.
+//
+// Imported the full CRI package is a nightmare.
+message Options {
+ string type_url = 1;
+ string config_path = 2;
+}
diff --git a/pkg/shim/v2/service.go b/pkg/shim/v2/service.go
index c67b1beba..1534152fc 100644
--- a/pkg/shim/v2/service.go
+++ b/pkg/shim/v2/service.go
@@ -27,34 +27,34 @@ import (
"github.com/BurntSushi/toml"
"github.com/containerd/cgroups"
- metrics "github.com/containerd/cgroups/stats/v1"
"github.com/containerd/console"
- eventstypes "github.com/containerd/containerd/api/events"
+ "github.com/containerd/containerd/api/events"
"github.com/containerd/containerd/api/types/task"
"github.com/containerd/containerd/errdefs"
- "github.com/containerd/containerd/events"
"github.com/containerd/containerd/log"
"github.com/containerd/containerd/mount"
"github.com/containerd/containerd/namespaces"
+ "github.com/containerd/containerd/pkg/process"
+ "github.com/containerd/containerd/pkg/stdio"
"github.com/containerd/containerd/runtime"
"github.com/containerd/containerd/runtime/linux/runctypes"
- rproc "github.com/containerd/containerd/runtime/proc"
"github.com/containerd/containerd/runtime/v2/shim"
taskAPI "github.com/containerd/containerd/runtime/v2/task"
- runtimeoptions "github.com/containerd/cri/pkg/api/runtimeoptions/v1"
+ "github.com/containerd/containerd/sys/reaper"
"github.com/containerd/typeurl"
- ptypes "github.com/gogo/protobuf/types"
+ "github.com/gogo/protobuf/types"
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/shim/runsc"
"gvisor.dev/gvisor/pkg/shim/v1/proc"
"gvisor.dev/gvisor/pkg/shim/v1/utils"
"gvisor.dev/gvisor/pkg/shim/v2/options"
+ "gvisor.dev/gvisor/pkg/shim/v2/runtimeoptions"
"gvisor.dev/gvisor/runsc/specutils"
)
var (
- empty = &ptypes.Empty{}
+ empty = &types.Empty{}
bufPool = sync.Pool{
New: func() interface{} {
buffer := make([]byte, 32<<10)
@@ -70,24 +70,23 @@ var _ = (taskAPI.TaskService)(&service{})
const configFile = "config.toml"
// New returns a new shim service that can be used via GRPC.
-func New(ctx context.Context, id string, publisher events.Publisher) (shim.Shim, error) {
+func New(ctx context.Context, id string, publisher shim.Publisher, cancel func()) (shim.Shim, error) {
ep, err := newOOMEpoller(publisher)
if err != nil {
return nil, err
}
- ctx, cancel := context.WithCancel(ctx)
go ep.run(ctx)
s := &service{
id: id,
context: ctx,
- processes: make(map[string]rproc.Process),
+ processes: make(map[string]process.Process),
events: make(chan interface{}, 128),
ec: proc.ExitCh,
oomPoller: ep,
cancel: cancel,
}
go s.processExits()
- runsc.Monitor = shim.Default
+ runsc.Monitor = reaper.Default
if err := s.initPlatform(); err != nil {
cancel()
return nil, fmt.Errorf("failed to initialized platform behavior: %w", err)
@@ -101,10 +100,10 @@ type service struct {
mu sync.Mutex
context context.Context
- task rproc.Process
- processes map[string]rproc.Process
+ task process.Process
+ processes map[string]process.Process
events chan interface{}
- platform rproc.Platform
+ platform stdio.Platform
opts options.Options
ec chan proc.Exit
oomPoller *epoller
@@ -141,7 +140,7 @@ func newCommand(ctx context.Context, containerdBinary, containerdAddress string)
return cmd, nil
}
-func (s *service) StartShim(ctx context.Context, id, containerdBinary, containerdAddress string) (string, error) {
+func (s *service) StartShim(ctx context.Context, id, containerdBinary, containerdAddress, containerdTTRPCAddress string) (string, error) {
cmd, err := newCommand(ctx, containerdBinary, containerdAddress)
if err != nil {
return "", err
@@ -270,7 +269,7 @@ func (s *service) Create(ctx context.Context, r *taskAPI.CreateTaskRequest) (_ *
break
}
if o.TypeUrl != options.OptionType {
- return nil, fmt.Errorf("unsupported runtimeoptions %q", o.TypeUrl)
+ return nil, fmt.Errorf("unsupported option type %q", o.TypeUrl)
}
path = o.ConfigPath
default:
@@ -415,7 +414,7 @@ func (s *service) Delete(ctx context.Context, r *taskAPI.DeleteRequest) (*taskAP
}
// Exec spawns an additional process inside the container.
-func (s *service) Exec(ctx context.Context, r *taskAPI.ExecProcessRequest) (*ptypes.Empty, error) {
+func (s *service) Exec(ctx context.Context, r *taskAPI.ExecProcessRequest) (*types.Empty, error) {
s.mu.Lock()
p := s.processes[r.ExecID]
s.mu.Unlock()
@@ -444,7 +443,7 @@ func (s *service) Exec(ctx context.Context, r *taskAPI.ExecProcessRequest) (*pty
}
// ResizePty resizes the terminal of a process.
-func (s *service) ResizePty(ctx context.Context, r *taskAPI.ResizePtyRequest) (*ptypes.Empty, error) {
+func (s *service) ResizePty(ctx context.Context, r *taskAPI.ResizePtyRequest) (*types.Empty, error) {
p, err := s.getProcess(r.ExecID)
if err != nil {
return nil, err
@@ -494,17 +493,17 @@ func (s *service) State(ctx context.Context, r *taskAPI.StateRequest) (*taskAPI.
}
// Pause the container.
-func (s *service) Pause(ctx context.Context, r *taskAPI.PauseRequest) (*ptypes.Empty, error) {
+func (s *service) Pause(ctx context.Context, r *taskAPI.PauseRequest) (*types.Empty, error) {
return empty, errdefs.ToGRPC(errdefs.ErrNotImplemented)
}
// Resume the container.
-func (s *service) Resume(ctx context.Context, r *taskAPI.ResumeRequest) (*ptypes.Empty, error) {
+func (s *service) Resume(ctx context.Context, r *taskAPI.ResumeRequest) (*types.Empty, error) {
return empty, errdefs.ToGRPC(errdefs.ErrNotImplemented)
}
// Kill a process with the provided signal.
-func (s *service) Kill(ctx context.Context, r *taskAPI.KillRequest) (*ptypes.Empty, error) {
+func (s *service) Kill(ctx context.Context, r *taskAPI.KillRequest) (*types.Empty, error) {
p, err := s.getProcess(r.ExecID)
if err != nil {
return nil, err
@@ -550,7 +549,7 @@ func (s *service) Pids(ctx context.Context, r *taskAPI.PidsRequest) (*taskAPI.Pi
}
// CloseIO closes the I/O context of a process.
-func (s *service) CloseIO(ctx context.Context, r *taskAPI.CloseIORequest) (*ptypes.Empty, error) {
+func (s *service) CloseIO(ctx context.Context, r *taskAPI.CloseIORequest) (*types.Empty, error) {
p, err := s.getProcess(r.ExecID)
if err != nil {
return nil, err
@@ -564,7 +563,7 @@ func (s *service) CloseIO(ctx context.Context, r *taskAPI.CloseIORequest) (*ptyp
}
// Checkpoint checkpoints the container.
-func (s *service) Checkpoint(ctx context.Context, r *taskAPI.CheckpointTaskRequest) (*ptypes.Empty, error) {
+func (s *service) Checkpoint(ctx context.Context, r *taskAPI.CheckpointTaskRequest) (*types.Empty, error) {
return empty, errdefs.ToGRPC(errdefs.ErrNotImplemented)
}
@@ -580,7 +579,7 @@ func (s *service) Connect(ctx context.Context, r *taskAPI.ConnectRequest) (*task
}, nil
}
-func (s *service) Shutdown(ctx context.Context, r *taskAPI.ShutdownRequest) (*ptypes.Empty, error) {
+func (s *service) Shutdown(ctx context.Context, r *taskAPI.ShutdownRequest) (*types.Empty, error) {
s.cancel()
os.Exit(0)
return empty, nil
@@ -608,52 +607,52 @@ func (s *service) Stats(ctx context.Context, r *taskAPI.StatsRequest) (*taskAPI.
// gvisor currently (as of 2020-03-03) only returns the total memory
// usage and current PID value[0]. However, we copy the common fields here
// so that future updates will propagate correct information. We're
- // using the metrics.Metrics structure so we're returning the same type
+ // using the cgroups.Metrics structure so we're returning the same type
// as runc.
//
// [0]: https://github.com/google/gvisor/blob/277a0d5a1fbe8272d4729c01ee4c6e374d047ebc/runsc/boot/events.go#L61-L81
- data, err := typeurl.MarshalAny(&metrics.Metrics{
- CPU: &metrics.CPUStat{
- Usage: &metrics.CPUUsage{
+ data, err := typeurl.MarshalAny(&cgroups.Metrics{
+ CPU: &cgroups.CPUStat{
+ Usage: &cgroups.CPUUsage{
Total: stats.Cpu.Usage.Total,
Kernel: stats.Cpu.Usage.Kernel,
User: stats.Cpu.Usage.User,
PerCPU: stats.Cpu.Usage.Percpu,
},
- Throttling: &metrics.Throttle{
+ Throttling: &cgroups.Throttle{
Periods: stats.Cpu.Throttling.Periods,
ThrottledPeriods: stats.Cpu.Throttling.ThrottledPeriods,
ThrottledTime: stats.Cpu.Throttling.ThrottledTime,
},
},
- Memory: &metrics.MemoryStat{
+ Memory: &cgroups.MemoryStat{
Cache: stats.Memory.Cache,
- Usage: &metrics.MemoryEntry{
+ Usage: &cgroups.MemoryEntry{
Limit: stats.Memory.Usage.Limit,
Usage: stats.Memory.Usage.Usage,
Max: stats.Memory.Usage.Max,
Failcnt: stats.Memory.Usage.Failcnt,
},
- Swap: &metrics.MemoryEntry{
+ Swap: &cgroups.MemoryEntry{
Limit: stats.Memory.Swap.Limit,
Usage: stats.Memory.Swap.Usage,
Max: stats.Memory.Swap.Max,
Failcnt: stats.Memory.Swap.Failcnt,
},
- Kernel: &metrics.MemoryEntry{
+ Kernel: &cgroups.MemoryEntry{
Limit: stats.Memory.Kernel.Limit,
Usage: stats.Memory.Kernel.Usage,
Max: stats.Memory.Kernel.Max,
Failcnt: stats.Memory.Kernel.Failcnt,
},
- KernelTCP: &metrics.MemoryEntry{
+ KernelTCP: &cgroups.MemoryEntry{
Limit: stats.Memory.KernelTCP.Limit,
Usage: stats.Memory.KernelTCP.Usage,
Max: stats.Memory.KernelTCP.Max,
Failcnt: stats.Memory.KernelTCP.Failcnt,
},
},
- Pids: &metrics.PidsStat{
+ Pids: &cgroups.PidsStat{
Current: stats.Pids.Current,
Limit: stats.Pids.Limit,
},
@@ -667,7 +666,7 @@ func (s *service) Stats(ctx context.Context, r *taskAPI.StatsRequest) (*taskAPI.
}
// Update updates a running container.
-func (s *service) Update(ctx context.Context, r *taskAPI.UpdateTaskRequest) (*ptypes.Empty, error) {
+func (s *service) Update(ctx context.Context, r *taskAPI.UpdateTaskRequest) (*types.Empty, error) {
return empty, errdefs.ToGRPC(errdefs.ErrNotImplemented)
}
@@ -707,7 +706,7 @@ func (s *service) checkProcesses(e proc.Exit) {
}
}
p.SetExited(e.Status)
- s.events <- &eventstypes.TaskExit{
+ s.events <- &events.TaskExit{
ContainerID: s.id,
ID: p.ID(),
Pid: uint32(p.Pid()),
@@ -719,7 +718,7 @@ func (s *service) checkProcesses(e proc.Exit) {
}
}
-func (s *service) allProcesses() (o []rproc.Process) {
+func (s *service) allProcesses() (o []process.Process) {
s.mu.Lock()
defer s.mu.Unlock()
for _, p := range s.processes {
@@ -749,18 +748,19 @@ func (s *service) getContainerPids(ctx context.Context, id string) ([]uint32, er
return pids, nil
}
-func (s *service) forward(publisher events.Publisher) {
+func (s *service) forward(publisher shim.Publisher) {
for e := range s.events {
ctx, cancel := context.WithTimeout(s.context, 5*time.Second)
err := publisher.Publish(ctx, getTopic(e), e)
cancel()
if err != nil {
- fmt.Errorf("post event: %w", err)
+ // Should not happen.
+ panic(fmt.Errorf("post event: %w", err))
}
}
}
-func (s *service) getProcess(execID string) (rproc.Process, error) {
+func (s *service) getProcess(execID string) (process.Process, error) {
s.mu.Lock()
defer s.mu.Unlock()
if execID == "" {
@@ -775,19 +775,19 @@ func (s *service) getProcess(execID string) (rproc.Process, error) {
func getTopic(e interface{}) string {
switch e.(type) {
- case *eventstypes.TaskCreate:
+ case *events.TaskCreate:
return runtime.TaskCreateEventTopic
- case *eventstypes.TaskStart:
+ case *events.TaskStart:
return runtime.TaskStartEventTopic
- case *eventstypes.TaskOOM:
+ case *events.TaskOOM:
return runtime.TaskOOMEventTopic
- case *eventstypes.TaskExit:
+ case *events.TaskExit:
return runtime.TaskExitEventTopic
- case *eventstypes.TaskDelete:
+ case *events.TaskDelete:
return runtime.TaskDeleteEventTopic
- case *eventstypes.TaskExecAdded:
+ case *events.TaskExecAdded:
return runtime.TaskExecAddedEventTopic
- case *eventstypes.TaskExecStarted:
+ case *events.TaskExecStarted:
return runtime.TaskExecStartedEventTopic
default:
log.L.Printf("no topic for type %#v", e)
@@ -795,7 +795,7 @@ func getTopic(e interface{}) string {
return runtime.TaskUnknownTopic
}
-func newInit(ctx context.Context, path, workDir, namespace string, platform rproc.Platform, r *proc.CreateConfig, options *options.Options, rootfs string) (*proc.Init, error) {
+func newInit(ctx context.Context, path, workDir, namespace string, platform stdio.Platform, r *proc.CreateConfig, options *options.Options, rootfs string) (*proc.Init, error) {
spec, err := utils.ReadSpec(r.Bundle)
if err != nil {
return nil, fmt.Errorf("read oci spec: %w", err)
@@ -805,7 +805,7 @@ func newInit(ctx context.Context, path, workDir, namespace string, platform rpro
}
runsc.FormatLogPath(r.ID, options.RunscConfig)
runtime := proc.NewRunsc(options.Root, path, namespace, options.BinaryName, options.RunscConfig)
- p := proc.New(r.ID, runtime, rproc.Stdio{
+ p := proc.New(r.ID, runtime, stdio.Stdio{
Stdin: r.Stdin,
Stdout: r.Stdout,
Stderr: r.Stderr,
@@ -819,6 +819,6 @@ func newInit(ctx context.Context, path, workDir, namespace string, platform rpro
p.IoGID = int(options.IoGid)
p.Sandbox = specutils.SpecContainerType(spec) == specutils.ContainerTypeSandbox
p.UserLog = utils.UserLogPath(spec)
- p.Monitor = shim.Default
+ p.Monitor = reaper.Default
return p, nil
}
diff --git a/pkg/shim/v2/service_linux.go b/pkg/shim/v2/service_linux.go
index 257c58812..1800ab90b 100644
--- a/pkg/shim/v2/service_linux.go
+++ b/pkg/shim/v2/service_linux.go
@@ -32,7 +32,7 @@ type linuxPlatform struct {
epoller *console.Epoller
}
-func (p *linuxPlatform) CopyConsole(ctx context.Context, console console.Console, stdin, stdout, stderr string, wg, cwg *sync.WaitGroup) (console.Console, error) {
+func (p *linuxPlatform) CopyConsole(ctx context.Context, console console.Console, stdin, stdout, stderr string, wg *sync.WaitGroup) (console.Console, error) {
if p.epoller == nil {
return nil, fmt.Errorf("uninitialized epoller")
}
@@ -47,9 +47,7 @@ func (p *linuxPlatform) CopyConsole(ctx context.Context, console console.Console
if err != nil {
return nil, err
}
- cwg.Add(1)
go func() {
- cwg.Done()
p := bufPool.Get().(*[]byte)
defer bufPool.Put(p)
io.CopyBuffer(epollConsole, in, *p)
@@ -65,9 +63,7 @@ func (p *linuxPlatform) CopyConsole(ctx context.Context, console console.Console
return nil, err
}
wg.Add(1)
- cwg.Add(1)
go func() {
- cwg.Done()
p := bufPool.Get().(*[]byte)
defer bufPool.Put(p)
io.CopyBuffer(outw, epollConsole, *p)
diff --git a/pkg/sleep/BUILD b/pkg/sleep/BUILD
index e131455f7..ae0fe1522 100644
--- a/pkg/sleep/BUILD
+++ b/pkg/sleep/BUILD
@@ -12,6 +12,7 @@ go_library(
"sleep_unsafe.go",
],
visibility = ["//:sandbox"],
+ deps = ["//pkg/sync"],
)
go_test(
diff --git a/pkg/sleep/sleep_test.go b/pkg/sleep/sleep_test.go
index af47e2ba1..1dd11707d 100644
--- a/pkg/sleep/sleep_test.go
+++ b/pkg/sleep/sleep_test.go
@@ -379,10 +379,7 @@ func TestRace(t *testing.T) {
// TestRaceInOrder tests that multiple wakers can continuously send wake requests to
// the sleeper and that the wakers are retrieved in the order asserted.
func TestRaceInOrder(t *testing.T) {
- const wakers = 100
- const wakeRequests = 10000
-
- w := make([]Waker, wakers)
+ w := make([]Waker, 10000)
s := Sleeper{}
// Associate each waker and start goroutines that will assert them.
@@ -390,19 +387,16 @@ func TestRaceInOrder(t *testing.T) {
s.AddWaker(&w[i], i)
}
go func() {
- n := 0
- for n < wakeRequests {
- wk := w[n%len(w)]
- wk.Assert()
- n++
+ for i := range w {
+ w[i].Assert()
}
}()
// Wait for all wake up notifications from all wakers.
- for i := 0; i < wakeRequests; i++ {
- v, _ := s.Fetch(true)
- if got, want := v, i%wakers; got != want {
- t.Fatalf("got %d want %d", got, want)
+ for want := range w {
+ got, _ := s.Fetch(true)
+ if got != want {
+ t.Fatalf("got %d want %d", got, want)
}
}
}
diff --git a/pkg/sleep/sleep_unsafe.go b/pkg/sleep/sleep_unsafe.go
index f68c12620..118805492 100644
--- a/pkg/sleep/sleep_unsafe.go
+++ b/pkg/sleep/sleep_unsafe.go
@@ -75,6 +75,8 @@ package sleep
import (
"sync/atomic"
"unsafe"
+
+ "gvisor.dev/gvisor/pkg/sync"
)
const (
@@ -323,7 +325,12 @@ func (s *Sleeper) enqueueAssertedWaker(w *Waker) {
//
// This struct is thread-safe, that is, its methods can be called concurrently
// by multiple goroutines.
+//
+// Note, it is not safe to copy a Waker as its fields are modified by value
+// (the pointer fields are individually modified with atomic operations).
type Waker struct {
+ _ sync.NoCopy
+
// s is the sleeper that this waker can wake up. Only one sleeper at a
// time is allowed. This field can have three classes of values:
// nil -- the waker is not asserted: it either is not associated with
diff --git a/pkg/sync/BUILD b/pkg/sync/BUILD
index d0d77e19c..4d47207f7 100644
--- a/pkg/sync/BUILD
+++ b/pkg/sync/BUILD
@@ -33,6 +33,7 @@ go_library(
"aliases.go",
"memmove_unsafe.go",
"mutex_unsafe.go",
+ "nocopy.go",
"norace_unsafe.go",
"race_unsafe.go",
"rwmutex_unsafe.go",
diff --git a/pkg/sync/nocopy.go b/pkg/sync/nocopy.go
new file mode 100644
index 000000000..722b29501
--- /dev/null
+++ b/pkg/sync/nocopy.go
@@ -0,0 +1,28 @@
+// Copyright 2020 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 sync
+
+// NoCopy may be embedded into structs which must not be copied
+// after the first use.
+//
+// See https://golang.org/issues/8005#issuecomment-190753527
+// for details.
+type NoCopy struct{}
+
+// Lock is a no-op used by -copylocks checker from `go vet`.
+func (*NoCopy) Lock() {}
+
+// Unlock is a no-op used by -copylocks checker from `go vet`.
+func (*NoCopy) Unlock() {}
diff --git a/pkg/tcpip/header/BUILD b/pkg/tcpip/header/BUILD
index 0cde694dc..d87797617 100644
--- a/pkg/tcpip/header/BUILD
+++ b/pkg/tcpip/header/BUILD
@@ -48,7 +48,7 @@ go_test(
"//pkg/rand",
"//pkg/tcpip",
"//pkg/tcpip/buffer",
- "@com_github_google_go-cmp//cmp:go_default_library",
+ "@com_github_google_go_cmp//cmp:go_default_library",
],
)
@@ -64,6 +64,6 @@ go_test(
deps = [
"//pkg/tcpip",
"//pkg/tcpip/buffer",
- "@com_github_google_go-cmp//cmp:go_default_library",
+ "@com_github_google_go_cmp//cmp:go_default_library",
],
)
diff --git a/pkg/tcpip/link/fdbased/endpoint_test.go b/pkg/tcpip/link/fdbased/endpoint_test.go
index eaee7e5d7..4bad930c7 100644
--- a/pkg/tcpip/link/fdbased/endpoint_test.go
+++ b/pkg/tcpip/link/fdbased/endpoint_test.go
@@ -500,3 +500,76 @@ func TestRecvMMsgDispatcherCapLength(t *testing.T) {
}
}
+
+// fakeNetworkDispatcher delivers packets to pkts.
+type fakeNetworkDispatcher struct {
+ pkts []*stack.PacketBuffer
+}
+
+func (d *fakeNetworkDispatcher) DeliverNetworkPacket(remote, local tcpip.LinkAddress, protocol tcpip.NetworkProtocolNumber, pkt *stack.PacketBuffer) {
+ d.pkts = append(d.pkts, pkt)
+}
+
+func TestDispatchPacketFormat(t *testing.T) {
+ for _, test := range []struct {
+ name string
+ newDispatcher func(fd int, e *endpoint) (linkDispatcher, error)
+ }{
+ {
+ name: "readVDispatcher",
+ newDispatcher: newReadVDispatcher,
+ },
+ {
+ name: "recvMMsgDispatcher",
+ newDispatcher: newRecvMMsgDispatcher,
+ },
+ } {
+ t.Run(test.name, func(t *testing.T) {
+ // Create a socket pair to send/recv.
+ fds, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_DGRAM, 0)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer syscall.Close(fds[0])
+ defer syscall.Close(fds[1])
+
+ data := []byte{
+ // Ethernet header.
+ 1, 2, 3, 4, 5, 60,
+ 1, 2, 3, 4, 5, 61,
+ 8, 0,
+ // Mock network header.
+ 40, 41, 42, 43,
+ }
+ err = syscall.Sendmsg(fds[1], data, nil, nil, 0)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // Create and run dispatcher once.
+ sink := &fakeNetworkDispatcher{}
+ d, err := test.newDispatcher(fds[0], &endpoint{
+ hdrSize: header.EthernetMinimumSize,
+ dispatcher: sink,
+ })
+ if err != nil {
+ t.Fatal(err)
+ }
+ if ok, err := d.dispatch(); !ok || err != nil {
+ t.Fatalf("d.dispatch() = %v, %v", ok, err)
+ }
+
+ // Verify packet.
+ if got, want := len(sink.pkts), 1; got != want {
+ t.Fatalf("len(sink.pkts) = %d, want %d", got, want)
+ }
+ pkt := sink.pkts[0]
+ if got, want := len(pkt.LinkHeader), header.EthernetMinimumSize; got != want {
+ t.Errorf("len(pkt.LinkHeader) = %d, want %d", got, want)
+ }
+ if got, want := pkt.Data.Size(), 4; got != want {
+ t.Errorf("pkt.Data.Size() = %d, want %d", got, want)
+ }
+ })
+ }
+}
diff --git a/pkg/tcpip/link/fdbased/packet_dispatchers.go b/pkg/tcpip/link/fdbased/packet_dispatchers.go
index f04738cfb..d8f2504b3 100644
--- a/pkg/tcpip/link/fdbased/packet_dispatchers.go
+++ b/pkg/tcpip/link/fdbased/packet_dispatchers.go
@@ -278,7 +278,7 @@ func (d *recvMMsgDispatcher) dispatch() (bool, *tcpip.Error) {
eth header.Ethernet
)
if d.e.hdrSize > 0 {
- eth = header.Ethernet(d.views[k][0])
+ eth = header.Ethernet(d.views[k][0][:header.EthernetMinimumSize])
p = eth.Type()
remote = eth.SourceAddress()
local = eth.DestinationAddress()
diff --git a/pkg/tcpip/network/ipv4/BUILD b/pkg/tcpip/network/ipv4/BUILD
index 78420d6e6..d142b4ffa 100644
--- a/pkg/tcpip/network/ipv4/BUILD
+++ b/pkg/tcpip/network/ipv4/BUILD
@@ -34,6 +34,6 @@ go_test(
"//pkg/tcpip/transport/tcp",
"//pkg/tcpip/transport/udp",
"//pkg/waiter",
- "@com_github_google_go-cmp//cmp:go_default_library",
+ "@com_github_google_go_cmp//cmp:go_default_library",
],
)
diff --git a/pkg/tcpip/network/ipv6/BUILD b/pkg/tcpip/network/ipv6/BUILD
index 3f71fc520..feada63dc 100644
--- a/pkg/tcpip/network/ipv6/BUILD
+++ b/pkg/tcpip/network/ipv6/BUILD
@@ -39,6 +39,6 @@ go_test(
"//pkg/tcpip/transport/icmp",
"//pkg/tcpip/transport/udp",
"//pkg/waiter",
- "@com_github_google_go-cmp//cmp:go_default_library",
+ "@com_github_google_go_cmp//cmp:go_default_library",
],
)
diff --git a/pkg/tcpip/stack/BUILD b/pkg/tcpip/stack/BUILD
index e65c731c2..6b9a6b316 100644
--- a/pkg/tcpip/stack/BUILD
+++ b/pkg/tcpip/stack/BUILD
@@ -27,6 +27,18 @@ go_template_instance(
},
)
+go_template_instance(
+ name = "tuple_list",
+ out = "tuple_list.go",
+ package = "stack",
+ prefix = "tuple",
+ template = "//pkg/ilist:generic_list",
+ types = {
+ "Element": "*tuple",
+ "Linker": "*tuple",
+ },
+)
+
go_library(
name = "stack",
srcs = [
@@ -35,6 +47,7 @@ go_library(
"forwarder.go",
"icmp_rate_limit.go",
"iptables.go",
+ "iptables_state.go",
"iptables_targets.go",
"iptables_types.go",
"linkaddrcache.go",
@@ -50,6 +63,7 @@ go_library(
"stack_global_state.go",
"stack_options.go",
"transport_demuxer.go",
+ "tuple_list.go",
],
visibility = ["//visibility:public"],
deps = [
@@ -95,7 +109,7 @@ go_test(
"//pkg/tcpip/transport/icmp",
"//pkg/tcpip/transport/udp",
"//pkg/waiter",
- "@com_github_google_go-cmp//cmp:go_default_library",
+ "@com_github_google_go_cmp//cmp:go_default_library",
],
)
diff --git a/pkg/tcpip/stack/conntrack.go b/pkg/tcpip/stack/conntrack.go
index af9c325ca..d39baf620 100644
--- a/pkg/tcpip/stack/conntrack.go
+++ b/pkg/tcpip/stack/conntrack.go
@@ -15,9 +15,12 @@
package stack
import (
+ "encoding/binary"
"sync"
+ "time"
"gvisor.dev/gvisor/pkg/tcpip"
+ "gvisor.dev/gvisor/pkg/tcpip/hash/jenkins"
"gvisor.dev/gvisor/pkg/tcpip/header"
"gvisor.dev/gvisor/pkg/tcpip/transport/tcpconntrack"
)
@@ -30,6 +33,10 @@ import (
//
// Currently, only TCP tracking is supported.
+// Our hash table has 16K buckets.
+// TODO(gvisor.dev/issue/170): These should be tunable.
+const numBuckets = 1 << 14
+
// Direction of the tuple.
type direction int
@@ -48,7 +55,12 @@ const (
// tuple holds a connection's identifying and manipulating data in one
// direction. It is immutable.
+//
+// +stateify savable
type tuple struct {
+ // tupleEntry is used to build an intrusive list of tuples.
+ tupleEntry
+
tupleID
// conn is the connection tracking entry this tuple belongs to.
@@ -61,6 +73,8 @@ type tuple struct {
// tupleID uniquely identifies a connection in one direction. It currently
// contains enough information to distinguish between any TCP or UDP
// connection, and will need to be extended to support other protocols.
+//
+// +stateify savable
type tupleID struct {
srcAddr tcpip.Address
srcPort uint16
@@ -83,6 +97,8 @@ func (ti tupleID) reply() tupleID {
}
// conn is a tracked connection.
+//
+// +stateify savable
type conn struct {
// original is the tuple in original direction. It is immutable.
original tuple
@@ -98,22 +114,67 @@ type conn struct {
tcbHook Hook
// mu protects tcb.
- mu sync.Mutex
+ mu sync.Mutex `state:"nosave"`
// tcb is TCB control block. It is used to keep track of states
// of tcp connection and is protected by mu.
tcb tcpconntrack.TCB
+
+ // lastUsed is the last time the connection saw a relevant packet, and
+ // is updated by each packet on the connection. It is protected by mu.
+ lastUsed time.Time `state:".(unixTime)"`
+}
+
+// timedOut returns whether the connection timed out based on its state.
+func (cn *conn) timedOut(now time.Time) bool {
+ const establishedTimeout = 5 * 24 * time.Hour
+ const defaultTimeout = 120 * time.Second
+ cn.mu.Lock()
+ defer cn.mu.Unlock()
+ if cn.tcb.State() == tcpconntrack.ResultAlive {
+ // Use the same default as Linux, which doesn't delete
+ // established connections for 5(!) days.
+ return now.Sub(cn.lastUsed) > establishedTimeout
+ }
+ // Use the same default as Linux, which lets connections in most states
+ // other than established remain for <= 120 seconds.
+ return now.Sub(cn.lastUsed) > defaultTimeout
}
// ConnTrack tracks all connections created for NAT rules. Most users are
// expected to only call handlePacket and createConnFor.
+//
+// ConnTrack keeps all connections in a slice of buckets, each of which holds a
+// linked list of tuples. This gives us some desirable properties:
+// - Each bucket has its own lock, lessening lock contention.
+// - The slice is large enough that lists stay short (<10 elements on average).
+// Thus traversal is fast.
+// - During linked list traversal we reap expired connections. This amortizes
+// the cost of reaping them and makes reapUnused faster.
+//
+// Locks are ordered by their location in the buckets slice. That is, a
+// goroutine that locks buckets[i] can only lock buckets[j] s.t. i < j.
+//
+// +stateify savable
type ConnTrack struct {
- // mu protects conns.
- mu sync.RWMutex
+ // seed is a one-time random value initialized at stack startup
+ // and is used in the calculation of hash keys for the list of buckets.
+ // It is immutable.
+ seed uint32
- // conns maintains a map of tuples needed for connection tracking for
- // iptables NAT rules. It is protected by mu.
- conns map[tupleID]tuple
+ // mu protects the buckets slice, but not buckets' contents. Only take
+ // the write lock if you are modifying the slice or saving for S/R.
+ mu sync.RWMutex `state:"nosave"`
+
+ // buckets is protected by mu.
+ buckets []bucket
+}
+
+// +stateify savable
+type bucket struct {
+ // mu protects tuples.
+ mu sync.Mutex `state:"nosave"`
+ tuples tupleList
}
// packetToTupleID converts packet to a tuple ID. It fails when pkt lacks a valid
@@ -143,8 +204,9 @@ func packetToTupleID(pkt *PacketBuffer) (tupleID, *tcpip.Error) {
// newConn creates new connection.
func newConn(orig, reply tupleID, manip manipType, hook Hook) *conn {
conn := conn{
- manip: manip,
- tcbHook: hook,
+ manip: manip,
+ tcbHook: hook,
+ lastUsed: time.Now(),
}
conn.original = tuple{conn: &conn, tupleID: orig}
conn.reply = tuple{conn: &conn, tupleID: reply, direction: dirReply}
@@ -162,14 +224,28 @@ func (ct *ConnTrack) connFor(pkt *PacketBuffer) (*conn, direction) {
return nil, dirOriginal
}
- ct.mu.Lock()
- defer ct.mu.Unlock()
-
- tuple, ok := ct.conns[tid]
- if !ok {
- return nil, dirOriginal
+ bucket := ct.bucket(tid)
+ now := time.Now()
+
+ ct.mu.RLock()
+ defer ct.mu.RUnlock()
+ ct.buckets[bucket].mu.Lock()
+ defer ct.buckets[bucket].mu.Unlock()
+
+ // Iterate over the tuples in a bucket, cleaning up any unused
+ // connections we find.
+ for other := ct.buckets[bucket].tuples.Front(); other != nil; other = other.Next() {
+ // Clean up any timed-out connections we happen to find.
+ if ct.reapTupleLocked(other, bucket, now) {
+ // The tuple expired.
+ continue
+ }
+ if tid == other.tupleID {
+ return other.conn, other.direction
+ }
}
- return tuple.conn, tuple.direction
+
+ return nil, dirOriginal
}
// createConnFor creates a new conn for pkt.
@@ -197,13 +273,31 @@ func (ct *ConnTrack) createConnFor(pkt *PacketBuffer, hook Hook, rt RedirectTarg
}
conn := newConn(tid, replyTID, manip, hook)
- // Add the changed tuple to the map.
- // TODO(gvisor.dev/issue/170): Need to support collisions using linked
- // list.
- ct.mu.Lock()
- defer ct.mu.Unlock()
- ct.conns[tid] = conn.original
- ct.conns[replyTID] = conn.reply
+ // Lock the buckets in the correct order.
+ tupleBucket := ct.bucket(tid)
+ replyBucket := ct.bucket(replyTID)
+ ct.mu.RLock()
+ defer ct.mu.RUnlock()
+ if tupleBucket < replyBucket {
+ ct.buckets[tupleBucket].mu.Lock()
+ ct.buckets[replyBucket].mu.Lock()
+ } else if tupleBucket > replyBucket {
+ ct.buckets[replyBucket].mu.Lock()
+ ct.buckets[tupleBucket].mu.Lock()
+ } else {
+ // Both tuples are in the same bucket.
+ ct.buckets[tupleBucket].mu.Lock()
+ }
+
+ // Add the tuple to the map.
+ ct.buckets[tupleBucket].tuples.PushFront(&conn.original)
+ ct.buckets[replyBucket].tuples.PushFront(&conn.reply)
+
+ // Unlocking can happen in any order.
+ ct.buckets[tupleBucket].mu.Unlock()
+ if tupleBucket != replyBucket {
+ ct.buckets[replyBucket].mu.Unlock()
+ }
return conn
}
@@ -297,35 +391,134 @@ func (ct *ConnTrack) handlePacket(pkt *PacketBuffer, hook Hook, gso *GSO, r *Rou
// other tcp states.
conn.mu.Lock()
defer conn.mu.Unlock()
- var st tcpconntrack.Result
- tcpHeader := header.TCP(pkt.TransportHeader)
- if conn.tcb.IsEmpty() {
+
+ // Mark the connection as having been used recently so it isn't reaped.
+ conn.lastUsed = time.Now()
+ // Update connection state.
+ if tcpHeader := header.TCP(pkt.TransportHeader); conn.tcb.IsEmpty() {
conn.tcb.Init(tcpHeader)
conn.tcbHook = hook
+ } else if hook == conn.tcbHook {
+ conn.tcb.UpdateStateOutbound(tcpHeader)
} else {
- switch hook {
- case conn.tcbHook:
- st = conn.tcb.UpdateStateOutbound(tcpHeader)
- default:
- st = conn.tcb.UpdateStateInbound(tcpHeader)
- }
+ conn.tcb.UpdateStateInbound(tcpHeader)
}
+}
+
+// bucket gets the conntrack bucket for a tupleID.
+func (ct *ConnTrack) bucket(id tupleID) int {
+ h := jenkins.Sum32(ct.seed)
+ h.Write([]byte(id.srcAddr))
+ h.Write([]byte(id.dstAddr))
+ shortBuf := make([]byte, 2)
+ binary.LittleEndian.PutUint16(shortBuf, id.srcPort)
+ h.Write([]byte(shortBuf))
+ binary.LittleEndian.PutUint16(shortBuf, id.dstPort)
+ h.Write([]byte(shortBuf))
+ binary.LittleEndian.PutUint16(shortBuf, uint16(id.transProto))
+ h.Write([]byte(shortBuf))
+ binary.LittleEndian.PutUint16(shortBuf, uint16(id.netProto))
+ h.Write([]byte(shortBuf))
+ ct.mu.RLock()
+ defer ct.mu.RUnlock()
+ return int(h.Sum32()) % len(ct.buckets)
+}
- // Delete conn if tcp connection is closed.
- if st == tcpconntrack.ResultClosedByPeer || st == tcpconntrack.ResultClosedBySelf || st == tcpconntrack.ResultReset {
- ct.deleteConn(conn)
+// reapUnused deletes timed out entries from the conntrack map. The rules for
+// reaping are:
+// - Most reaping occurs in connFor, which is called on each packet. connFor
+// cleans up the bucket the packet's connection maps to. Thus calls to
+// reapUnused should be fast.
+// - Each call to reapUnused traverses a fraction of the conntrack table.
+// Specifically, it traverses len(ct.buckets)/fractionPerReaping.
+// - After reaping, reapUnused decides when it should next run based on the
+// ratio of expired connections to examined connections. If the ratio is
+// greater than maxExpiredPct, it schedules the next run quickly. Otherwise it
+// slightly increases the interval between runs.
+// - maxFullTraversal caps the time it takes to traverse the entire table.
+//
+// reapUnused returns the next bucket that should be checked and the time after
+// which it should be called again.
+func (ct *ConnTrack) reapUnused(start int, prevInterval time.Duration) (int, time.Duration) {
+ // TODO(gvisor.dev/issue/170): This can be more finely controlled, as
+ // it is in Linux via sysctl.
+ const fractionPerReaping = 128
+ const maxExpiredPct = 50
+ const maxFullTraversal = 60 * time.Second
+ const minInterval = 10 * time.Millisecond
+ const maxInterval = maxFullTraversal / fractionPerReaping
+
+ now := time.Now()
+ checked := 0
+ expired := 0
+ var idx int
+ ct.mu.RLock()
+ defer ct.mu.RUnlock()
+ for i := 0; i < len(ct.buckets)/fractionPerReaping; i++ {
+ idx = (i + start) % len(ct.buckets)
+ ct.buckets[idx].mu.Lock()
+ for tuple := ct.buckets[idx].tuples.Front(); tuple != nil; tuple = tuple.Next() {
+ checked++
+ if ct.reapTupleLocked(tuple, idx, now) {
+ expired++
+ }
+ }
+ ct.buckets[idx].mu.Unlock()
+ }
+ // We already checked buckets[idx].
+ idx++
+
+ // If half or more of the connections are expired, the table has gotten
+ // stale. Reschedule quickly.
+ expiredPct := 0
+ if checked != 0 {
+ expiredPct = expired * 100 / checked
+ }
+ if expiredPct > maxExpiredPct {
+ return idx, minInterval
+ }
+ if interval := prevInterval + minInterval; interval <= maxInterval {
+ // Increment the interval between runs.
+ return idx, interval
}
+ // We've hit the maximum interval.
+ return idx, maxInterval
}
-// deleteConn deletes the connection.
-func (ct *ConnTrack) deleteConn(conn *conn) {
- if conn == nil {
- return
+// reapTupleLocked tries to remove tuple and its reply from the table. It
+// returns whether the tuple's connection has timed out.
+//
+// Preconditions: ct.mu is locked for reading and bucket is locked.
+func (ct *ConnTrack) reapTupleLocked(tuple *tuple, bucket int, now time.Time) bool {
+ if !tuple.conn.timedOut(now) {
+ return false
}
- ct.mu.Lock()
- defer ct.mu.Unlock()
+ // To maintain lock order, we can only reap these tuples if the reply
+ // appears later in the table.
+ replyBucket := ct.bucket(tuple.reply())
+ if bucket > replyBucket {
+ return true
+ }
+
+ // Don't re-lock if both tuples are in the same bucket.
+ differentBuckets := bucket != replyBucket
+ if differentBuckets {
+ ct.buckets[replyBucket].mu.Lock()
+ }
+
+ // We have the buckets locked and can remove both tuples.
+ if tuple.direction == dirOriginal {
+ ct.buckets[replyBucket].tuples.Remove(&tuple.conn.reply)
+ } else {
+ ct.buckets[replyBucket].tuples.Remove(&tuple.conn.original)
+ }
+ ct.buckets[bucket].tuples.Remove(tuple)
+
+ // Don't re-unlock if both tuples are in the same bucket.
+ if differentBuckets {
+ ct.buckets[replyBucket].mu.Unlock()
+ }
- delete(ct.conns, conn.original.tupleID)
- delete(ct.conns, conn.reply.tupleID)
+ return true
}
diff --git a/pkg/tcpip/stack/iptables.go b/pkg/tcpip/stack/iptables.go
index 974d77c36..f846ea2e5 100644
--- a/pkg/tcpip/stack/iptables.go
+++ b/pkg/tcpip/stack/iptables.go
@@ -16,6 +16,7 @@ package stack
import (
"fmt"
+ "time"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/header"
@@ -41,6 +42,9 @@ const (
// underflow.
const HookUnset = -1
+// reaperDelay is how long to wait before starting to reap connections.
+const reaperDelay = 5 * time.Second
+
// DefaultTables returns a default set of tables. Each chain is set to accept
// all packets.
func DefaultTables() *IPTables {
@@ -112,8 +116,9 @@ func DefaultTables() *IPTables {
Output: []string{TablenameMangle, TablenameNat, TablenameFilter},
},
connections: ConnTrack{
- conns: make(map[tupleID]tuple),
+ seed: generateRandUint32(),
},
+ reaperDone: make(chan struct{}, 1),
}
}
@@ -169,6 +174,12 @@ func (it *IPTables) GetTable(name string) (Table, bool) {
func (it *IPTables) ReplaceTable(name string, table Table) {
it.mu.Lock()
defer it.mu.Unlock()
+ // If iptables is being enabled, initialize the conntrack table and
+ // reaper.
+ if !it.modified {
+ it.connections.buckets = make([]bucket, numBuckets)
+ it.startReaper(reaperDelay)
+ }
it.modified = true
it.tables[name] = table
}
@@ -249,6 +260,35 @@ func (it *IPTables) Check(hook Hook, pkt *PacketBuffer, gso *GSO, r *Route, addr
return true
}
+// beforeSave is invoked by stateify.
+func (it *IPTables) beforeSave() {
+ // Ensure the reaper exits cleanly.
+ it.reaperDone <- struct{}{}
+ // Prevent others from modifying the connection table.
+ it.connections.mu.Lock()
+}
+
+// afterLoad is invoked by stateify.
+func (it *IPTables) afterLoad() {
+ it.startReaper(reaperDelay)
+}
+
+// startReaper starts a goroutine that wakes up periodically to reap timed out
+// connections.
+func (it *IPTables) startReaper(interval time.Duration) {
+ go func() { // S/R-SAFE: reaperDone is signalled when iptables is saved.
+ bucket := 0
+ for {
+ select {
+ case <-it.reaperDone:
+ return
+ case <-time.After(interval):
+ bucket, interval = it.connections.reapUnused(bucket, interval)
+ }
+ }
+ }()
+}
+
// CheckPackets runs pkts through the rules for hook and returns a map of packets that
// should not go forward.
//
diff --git a/pkg/tcpip/stack/iptables_state.go b/pkg/tcpip/stack/iptables_state.go
new file mode 100644
index 000000000..529e02a07
--- /dev/null
+++ b/pkg/tcpip/stack/iptables_state.go
@@ -0,0 +1,40 @@
+// Copyright 2020 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 stack
+
+import (
+ "time"
+)
+
+// +stateify savable
+type unixTime struct {
+ second int64
+ nano int64
+}
+
+// saveLastUsed is invoked by stateify.
+func (cn *conn) saveLastUsed() unixTime {
+ return unixTime{cn.lastUsed.Unix(), cn.lastUsed.UnixNano()}
+}
+
+// loadLastUsed is invoked by stateify.
+func (cn *conn) loadLastUsed(unix unixTime) {
+ cn.lastUsed = time.Unix(unix.second, unix.nano)
+}
+
+// beforeSave is invoked by stateify.
+func (ct *ConnTrack) beforeSave() {
+ ct.mu.Lock()
+}
diff --git a/pkg/tcpip/stack/iptables_types.go b/pkg/tcpip/stack/iptables_types.go
index c528ec381..eb70e3104 100644
--- a/pkg/tcpip/stack/iptables_types.go
+++ b/pkg/tcpip/stack/iptables_types.go
@@ -78,6 +78,8 @@ const (
)
// IPTables holds all the tables for a netstack.
+//
+// +stateify savable
type IPTables struct {
// mu protects tables, priorities, and modified.
mu sync.RWMutex
@@ -97,10 +99,15 @@ type IPTables struct {
modified bool
connections ConnTrack
+
+ // reaperDone can be signalled to stop the reaper goroutine.
+ reaperDone chan struct{}
}
// A Table defines a set of chains and hooks into the network stack. It is
// really just a list of rules.
+//
+// +stateify savable
type Table struct {
// Rules holds the rules that make up the table.
Rules []Rule
@@ -130,6 +137,8 @@ func (table *Table) ValidHooks() uint32 {
// contains zero or more matchers, each of which is a specification of which
// packets this rule applies to. If there are no matchers in the rule, it
// applies to any packet.
+//
+// +stateify savable
type Rule struct {
// Filter holds basic IP filtering fields common to every rule.
Filter IPHeaderFilter
@@ -142,6 +151,8 @@ type Rule struct {
}
// IPHeaderFilter holds basic IP filtering data common to every rule.
+//
+// +stateify savable
type IPHeaderFilter struct {
// Protocol matches the transport protocol.
Protocol tcpip.TransportProtocolNumber
diff --git a/pkg/tcpip/stack/packet_buffer.go b/pkg/tcpip/stack/packet_buffer.go
index 1b5da6017..e3556d5d2 100644
--- a/pkg/tcpip/stack/packet_buffer.go
+++ b/pkg/tcpip/stack/packet_buffer.go
@@ -14,6 +14,7 @@
package stack
import (
+ "gvisor.dev/gvisor/pkg/sync"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/buffer"
)
@@ -24,7 +25,7 @@ import (
// multiple endpoints. Clone() should be called in such cases so that
// modifications to the Data field do not affect other copies.
type PacketBuffer struct {
- _ noCopy
+ _ sync.NoCopy
// PacketBufferEntry is used to build an intrusive list of
// PacketBuffers.
@@ -102,14 +103,3 @@ func (pk *PacketBuffer) Clone() *PacketBuffer {
NatDone: pk.NatDone,
}
}
-
-// noCopy may be embedded into structs which must not be copied
-// after the first use.
-//
-// See https://golang.org/issues/8005#issuecomment-190753527
-// for details.
-type noCopy struct{}
-
-// Lock is a no-op used by -copylocks checker from `go vet`.
-func (*noCopy) Lock() {}
-func (*noCopy) Unlock() {}
diff --git a/pkg/tcpip/stack/stack.go b/pkg/tcpip/stack/stack.go
index cdcfb8321..0aa815447 100644
--- a/pkg/tcpip/stack/stack.go
+++ b/pkg/tcpip/stack/stack.go
@@ -425,6 +425,7 @@ type Stack struct {
handleLocal bool
// tables are the iptables packet filtering and manipulation rules.
+ // TODO(gvisor.dev/issue/170): S/R this field.
tables *IPTables
// resumableEndpoints is a list of endpoints that need to be resumed if the
diff --git a/pkg/tcpip/tcpip.go b/pkg/tcpip/tcpip.go
index 25534a10d..71bcee785 100644
--- a/pkg/tcpip/tcpip.go
+++ b/pkg/tcpip/tcpip.go
@@ -782,7 +782,7 @@ type CongestionControlOption string
// control algorithms.
type AvailableCongestionControlOption string
-// buffer moderation.
+// ModerateReceiveBufferOption is used by buffer moderation.
type ModerateReceiveBufferOption bool
// TCPLingerTimeoutOption is used by SetSockOpt/GetSockOpt to set/get the
@@ -855,7 +855,10 @@ type OutOfBandInlineOption int
// a default TTL.
type DefaultTTLOption uint8
-//
+// SocketDetachFilterOption is used by SetSockOpt to detach a previously attached
+// classic BPF filter on a given endpoint.
+type SocketDetachFilterOption int
+
// IPPacketInfo is the message structure for IP_PKTINFO.
//
// +stateify savable
@@ -1244,6 +1247,9 @@ type UDPStats struct {
// ChecksumErrors is the number of datagrams dropped due to bad checksums.
ChecksumErrors *StatCounter
+
+ // InvalidSourceAddress is the number of invalid sourced datagrams dropped.
+ InvalidSourceAddress *StatCounter
}
// Stats holds statistics about the networking stack.
diff --git a/pkg/tcpip/timer.go b/pkg/tcpip/timer.go
index 59f3b391f..5554c573f 100644
--- a/pkg/tcpip/timer.go
+++ b/pkg/tcpip/timer.go
@@ -15,8 +15,9 @@
package tcpip
import (
- "sync"
"time"
+
+ "gvisor.dev/gvisor/pkg/sync"
)
// cancellableTimerInstance is a specific instance of CancellableTimer.
@@ -92,6 +93,8 @@ func (t *cancellableTimerInstance) stop() {
// Note, it is not safe to copy a CancellableTimer as its timer instance creates
// a closure over the address of the CancellableTimer.
type CancellableTimer struct {
+ _ sync.NoCopy
+
// The active instance of a cancellable timer.
instance cancellableTimerInstance
@@ -157,22 +160,6 @@ func (t *CancellableTimer) Reset(d time.Duration) {
}
}
-// Lock is a no-op used by the copylocks checker from go vet.
-//
-// See CancellableTimer for details about why it shouldn't be copied.
-//
-// See https://github.com/golang/go/issues/8005#issuecomment-190753527 for more
-// details about the copylocks checker.
-func (*CancellableTimer) Lock() {}
-
-// Unlock is a no-op used by the copylocks checker from go vet.
-//
-// See CancellableTimer for details about why it shouldn't be copied.
-//
-// See https://github.com/golang/go/issues/8005#issuecomment-190753527 for more
-// details about the copylocks checker.
-func (*CancellableTimer) Unlock() {}
-
// NewCancellableTimer returns an unscheduled CancellableTimer with the given
// locker and fn.
//
diff --git a/pkg/tcpip/transport/icmp/endpoint.go b/pkg/tcpip/transport/icmp/endpoint.go
index 62d1acad4..678f4e016 100644
--- a/pkg/tcpip/transport/icmp/endpoint.go
+++ b/pkg/tcpip/transport/icmp/endpoint.go
@@ -344,6 +344,10 @@ func (e *endpoint) Peek([][]byte) (int64, tcpip.ControlMessages, *tcpip.Error) {
// SetSockOpt sets a socket option.
func (e *endpoint) SetSockOpt(opt interface{}) *tcpip.Error {
+ switch opt.(type) {
+ case tcpip.SocketDetachFilterOption:
+ return nil
+ }
return nil
}
diff --git a/pkg/tcpip/transport/packet/endpoint.go b/pkg/tcpip/transport/packet/endpoint.go
index a8f8454dd..57b7f5c19 100644
--- a/pkg/tcpip/transport/packet/endpoint.go
+++ b/pkg/tcpip/transport/packet/endpoint.go
@@ -278,7 +278,13 @@ func (ep *endpoint) Readiness(mask waiter.EventMask) waiter.EventMask {
// used with SetSockOpt, and this function always returns
// tcpip.ErrNotSupported.
func (ep *endpoint) SetSockOpt(opt interface{}) *tcpip.Error {
- return tcpip.ErrUnknownProtocolOption
+ switch opt.(type) {
+ case tcpip.SocketDetachFilterOption:
+ return nil
+
+ default:
+ return tcpip.ErrUnknownProtocolOption
+ }
}
// SetSockOptBool implements tcpip.Endpoint.SetSockOptBool.
diff --git a/pkg/tcpip/transport/raw/endpoint.go b/pkg/tcpip/transport/raw/endpoint.go
index 5b6e7d102..c2e9fd29f 100644
--- a/pkg/tcpip/transport/raw/endpoint.go
+++ b/pkg/tcpip/transport/raw/endpoint.go
@@ -506,7 +506,13 @@ func (e *endpoint) Readiness(mask waiter.EventMask) waiter.EventMask {
// SetSockOpt implements tcpip.Endpoint.SetSockOpt.
func (e *endpoint) SetSockOpt(opt interface{}) *tcpip.Error {
- return tcpip.ErrUnknownProtocolOption
+ switch opt.(type) {
+ case tcpip.SocketDetachFilterOption:
+ return nil
+
+ default:
+ return tcpip.ErrUnknownProtocolOption
+ }
}
// SetSockOptBool implements tcpip.Endpoint.SetSockOptBool.
diff --git a/pkg/tcpip/transport/tcp/endpoint.go b/pkg/tcpip/transport/tcp/endpoint.go
index caac6ef57..83dc10ed0 100644
--- a/pkg/tcpip/transport/tcp/endpoint.go
+++ b/pkg/tcpip/transport/tcp/endpoint.go
@@ -1792,6 +1792,9 @@ func (e *endpoint) SetSockOpt(opt interface{}) *tcpip.Error {
e.deferAccept = time.Duration(v)
e.UnlockUser()
+ case tcpip.SocketDetachFilterOption:
+ return nil
+
default:
return nil
}
diff --git a/pkg/tcpip/transport/tcpconntrack/tcp_conntrack.go b/pkg/tcpip/transport/tcpconntrack/tcp_conntrack.go
index 12bc1b5b5..558b06df0 100644
--- a/pkg/tcpip/transport/tcpconntrack/tcp_conntrack.go
+++ b/pkg/tcpip/transport/tcpconntrack/tcp_conntrack.go
@@ -106,6 +106,11 @@ func (t *TCB) UpdateStateOutbound(tcp header.TCP) Result {
return st
}
+// State returns the current state of the TCB.
+func (t *TCB) State() Result {
+ return t.state
+}
+
// IsAlive returns true as long as the connection is established(Alive)
// or connecting state.
func (t *TCB) IsAlive() bool {
diff --git a/pkg/tcpip/transport/udp/endpoint.go b/pkg/tcpip/transport/udp/endpoint.go
index 0584ec8dc..a14643ae8 100644
--- a/pkg/tcpip/transport/udp/endpoint.go
+++ b/pkg/tcpip/transport/udp/endpoint.go
@@ -816,6 +816,9 @@ func (e *endpoint) SetSockOpt(opt interface{}) *tcpip.Error {
e.mu.Lock()
e.bindToDevice = id
e.mu.Unlock()
+
+ case tcpip.SocketDetachFilterOption:
+ return nil
}
return nil
}
@@ -1377,6 +1380,15 @@ func (e *endpoint) HandlePacket(r *stack.Route, id stack.TransportEndpointID, pk
return
}
+ // Never receive from a multicast address.
+ if header.IsV4MulticastAddress(id.RemoteAddress) ||
+ header.IsV6MulticastAddress(id.RemoteAddress) {
+ e.stack.Stats().UDP.InvalidSourceAddress.Increment()
+ e.stack.Stats().IP.InvalidSourceAddressesReceived.Increment()
+ e.stats.ReceiveErrors.MalformedPacketsReceived.Increment()
+ return
+ }
+
// Verify checksum unless RX checksum offload is enabled.
// On IPv4, UDP checksum is optional, and a zero value means
// the transmitter omitted the checksum generation (RFC768).
@@ -1395,10 +1407,10 @@ func (e *endpoint) HandlePacket(r *stack.Route, id stack.TransportEndpointID, pk
}
}
- e.rcvMu.Lock()
e.stack.Stats().UDP.PacketsReceived.Increment()
e.stats.PacketsReceived.Increment()
+ e.rcvMu.Lock()
// Drop the packet if our buffer is currently full.
if !e.rcvReady || e.rcvClosed {
e.rcvMu.Unlock()
diff --git a/pkg/tcpip/transport/udp/udp_test.go b/pkg/tcpip/transport/udp/udp_test.go
index 91ba031fa..90781cf49 100644
--- a/pkg/tcpip/transport/udp/udp_test.go
+++ b/pkg/tcpip/transport/udp/udp_test.go
@@ -83,16 +83,18 @@ type header4Tuple struct {
type testFlow int
const (
- unicastV4 testFlow = iota // V4 unicast on a V4 socket
- unicastV4in6 // V4-mapped unicast on a V6-dual socket
- unicastV6 // V6 unicast on a V6 socket
- unicastV6Only // V6 unicast on a V6-only socket
- multicastV4 // V4 multicast on a V4 socket
- multicastV4in6 // V4-mapped multicast on a V6-dual socket
- multicastV6 // V6 multicast on a V6 socket
- multicastV6Only // V6 multicast on a V6-only socket
- broadcast // V4 broadcast on a V4 socket
- broadcastIn6 // V4-mapped broadcast on a V6-dual socket
+ unicastV4 testFlow = iota // V4 unicast on a V4 socket
+ unicastV4in6 // V4-mapped unicast on a V6-dual socket
+ unicastV6 // V6 unicast on a V6 socket
+ unicastV6Only // V6 unicast on a V6-only socket
+ multicastV4 // V4 multicast on a V4 socket
+ multicastV4in6 // V4-mapped multicast on a V6-dual socket
+ multicastV6 // V6 multicast on a V6 socket
+ multicastV6Only // V6 multicast on a V6-only socket
+ broadcast // V4 broadcast on a V4 socket
+ broadcastIn6 // V4-mapped broadcast on a V6-dual socket
+ reverseMulticast4 // V4 multicast src. Must fail.
+ reverseMulticast6 // V6 multicast src. Must fail.
)
func (flow testFlow) String() string {
@@ -117,6 +119,10 @@ func (flow testFlow) String() string {
return "broadcast"
case broadcastIn6:
return "broadcastIn6"
+ case reverseMulticast4:
+ return "reverseMulticast4"
+ case reverseMulticast6:
+ return "reverseMulticast6"
default:
return "unknown"
}
@@ -168,6 +174,9 @@ func (flow testFlow) header4Tuple(d packetDirection) header4Tuple {
h.dstAddr.Addr = multicastV6Addr
}
}
+ if flow.isReverseMulticast() {
+ h.srcAddr.Addr = flow.getMcastAddr()
+ }
return h
}
@@ -199,9 +208,9 @@ func (flow testFlow) netProto() tcpip.NetworkProtocolNumber {
// endpoint for this flow.
func (flow testFlow) sockProto() tcpip.NetworkProtocolNumber {
switch flow {
- case unicastV4in6, unicastV6, unicastV6Only, multicastV4in6, multicastV6, multicastV6Only, broadcastIn6:
+ case unicastV4in6, unicastV6, unicastV6Only, multicastV4in6, multicastV6, multicastV6Only, broadcastIn6, reverseMulticast6:
return ipv6.ProtocolNumber
- case unicastV4, multicastV4, broadcast:
+ case unicastV4, multicastV4, broadcast, reverseMulticast4:
return ipv4.ProtocolNumber
default:
panic(fmt.Sprintf("invalid testFlow given: %d", flow))
@@ -224,7 +233,7 @@ func (flow testFlow) isV6Only() bool {
switch flow {
case unicastV6Only, multicastV6Only:
return true
- case unicastV4, unicastV4in6, unicastV6, multicastV4, multicastV4in6, multicastV6, broadcast, broadcastIn6:
+ case unicastV4, unicastV4in6, unicastV6, multicastV4, multicastV4in6, multicastV6, broadcast, broadcastIn6, reverseMulticast4, reverseMulticast6:
return false
default:
panic(fmt.Sprintf("invalid testFlow given: %d", flow))
@@ -235,7 +244,7 @@ func (flow testFlow) isMulticast() bool {
switch flow {
case multicastV4, multicastV4in6, multicastV6, multicastV6Only:
return true
- case unicastV4, unicastV4in6, unicastV6, unicastV6Only, broadcast, broadcastIn6:
+ case unicastV4, unicastV4in6, unicastV6, unicastV6Only, broadcast, broadcastIn6, reverseMulticast4, reverseMulticast6:
return false
default:
panic(fmt.Sprintf("invalid testFlow given: %d", flow))
@@ -246,7 +255,7 @@ func (flow testFlow) isBroadcast() bool {
switch flow {
case broadcast, broadcastIn6:
return true
- case unicastV4, unicastV4in6, unicastV6, unicastV6Only, multicastV4, multicastV4in6, multicastV6, multicastV6Only:
+ case unicastV4, unicastV4in6, unicastV6, unicastV6Only, multicastV4, multicastV4in6, multicastV6, multicastV6Only, reverseMulticast4, reverseMulticast6:
return false
default:
panic(fmt.Sprintf("invalid testFlow given: %d", flow))
@@ -257,13 +266,22 @@ func (flow testFlow) isMapped() bool {
switch flow {
case unicastV4in6, multicastV4in6, broadcastIn6:
return true
- case unicastV4, unicastV6, unicastV6Only, multicastV4, multicastV6, multicastV6Only, broadcast:
+ case unicastV4, unicastV6, unicastV6Only, multicastV4, multicastV6, multicastV6Only, broadcast, reverseMulticast4, reverseMulticast6:
return false
default:
panic(fmt.Sprintf("invalid testFlow given: %d", flow))
}
}
+func (flow testFlow) isReverseMulticast() bool {
+ switch flow {
+ case reverseMulticast4, reverseMulticast6:
+ return true
+ default:
+ return false
+ }
+}
+
type testContext struct {
t *testing.T
linkEP *channel.Endpoint
@@ -872,6 +890,60 @@ func TestV4ReadOnBoundToBroadcast(t *testing.T) {
}
}
+// TestReadFromMulticast checks that an endpoint will NOT receive a packet
+// that was sent with multicast SOURCE address.
+func TestReadFromMulticast(t *testing.T) {
+ for _, flow := range []testFlow{reverseMulticast4, reverseMulticast6} {
+ t.Run(fmt.Sprintf("flow:%s", flow), func(t *testing.T) {
+ c := newDualTestContext(t, defaultMTU)
+ defer c.cleanup()
+
+ c.createEndpointForFlow(flow)
+
+ if err := c.ep.Bind(tcpip.FullAddress{Port: stackPort}); err != nil {
+ t.Fatalf("Bind failed: %s", err)
+ }
+ testFailingRead(c, flow, false /* expectReadError */)
+ })
+ }
+}
+
+// TestReadFromMulticaststats checks that a discarded packet
+// that that was sent with multicast SOURCE address increments
+// the correct counters and that a regular packet does not.
+func TestReadFromMulticastStats(t *testing.T) {
+ t.Helper()
+ for _, flow := range []testFlow{reverseMulticast4, reverseMulticast6, unicastV4} {
+ t.Run(fmt.Sprintf("flow:%s", flow), func(t *testing.T) {
+ c := newDualTestContext(t, defaultMTU)
+ defer c.cleanup()
+
+ c.createEndpointForFlow(flow)
+
+ if err := c.ep.Bind(tcpip.FullAddress{Port: stackPort}); err != nil {
+ t.Fatalf("Bind failed: %s", err)
+ }
+
+ payload := newPayload()
+ c.injectPacket(flow, payload)
+
+ var want uint64 = 0
+ if flow.isReverseMulticast() {
+ want = 1
+ }
+ if got := c.s.Stats().IP.InvalidSourceAddressesReceived.Value(); got != want {
+ t.Errorf("got stats.IP.InvalidSourceAddressesReceived.Value() = %d, want = %d", got, want)
+ }
+ if got := c.s.Stats().UDP.InvalidSourceAddress.Value(); got != want {
+ t.Errorf("got stats.UDP.InvalidSourceAddress.Value() = %d, want = %d", got, want)
+ }
+ if got := c.ep.Stats().(*tcpip.TransportEndpointStats).ReceiveErrors.MalformedPacketsReceived.Value(); got != want {
+ t.Errorf("got EP Stats.ReceiveErrors.MalformedPacketsReceived stats = %d, want = %d", got, want)
+ }
+ })
+ }
+}
+
// TestV4ReadBroadcastOnBoundToWildcard checks that an endpoint can bind to ANY
// and receive broadcast and unicast data.
func TestV4ReadBroadcastOnBoundToWildcard(t *testing.T) {
diff --git a/pkg/test/criutil/criutil.go b/pkg/test/criutil/criutil.go
index 4c63d669a..66f10c016 100644
--- a/pkg/test/criutil/criutil.go
+++ b/pkg/test/criutil/criutil.go
@@ -103,6 +103,9 @@ func (cc *Crictl) Create(podID, contSpecFile, sbSpecFile string) (string, error)
// need to parse the version and add an appropriate --no-pull argument
// since the image has already been loaded locally.
out, err := cc.run("-v")
+ if err != nil {
+ return "", err
+ }
r := regexp.MustCompile("crictl version ([0-9]+)\\.([0-9]+)\\.([0-9+])")
vs := r.FindStringSubmatch(out)
if len(vs) != 4 {
diff --git a/pkg/test/dockerutil/dockerutil.go b/pkg/test/dockerutil/dockerutil.go
index f95ae3cd1..df09babf3 100644
--- a/pkg/test/dockerutil/dockerutil.go
+++ b/pkg/test/dockerutil/dockerutil.go
@@ -119,3 +119,8 @@ func Save(logger testutil.Logger, image string, w io.Writer) error {
cmd.Stdout = w // Send directly to the writer.
return cmd.Run()
}
+
+// Runtime returns the value of the flag runtime.
+func Runtime() string {
+ return *runtime
+}
diff --git a/pkg/test/testutil/BUILD b/pkg/test/testutil/BUILD
index 03b1b4677..2d8f56bc0 100644
--- a/pkg/test/testutil/BUILD
+++ b/pkg/test/testutil/BUILD
@@ -15,6 +15,6 @@ go_library(
"//runsc/boot",
"//runsc/specutils",
"@com_github_cenkalti_backoff//:go_default_library",
- "@com_github_opencontainers_runtime-spec//specs-go:go_default_library",
+ "@com_github_opencontainers_runtime_spec//specs-go:go_default_library",
],
)
diff --git a/runsc/boot/BUILD b/runsc/boot/BUILD
index aad2a41de..55d45aaa6 100644
--- a/runsc/boot/BUILD
+++ b/runsc/boot/BUILD
@@ -106,7 +106,7 @@ go_library(
"//runsc/boot/pprof",
"//runsc/specutils",
"@com_github_golang_protobuf//proto:go_default_library",
- "@com_github_opencontainers_runtime-spec//specs-go:go_default_library",
+ "@com_github_opencontainers_runtime_spec//specs-go:go_default_library",
"@org_golang_x_sys//unix:go_default_library",
],
)
@@ -131,7 +131,7 @@ go_test(
"//pkg/sync",
"//pkg/unet",
"//runsc/fsgofer",
- "@com_github_opencontainers_runtime-spec//specs-go:go_default_library",
+ "@com_github_opencontainers_runtime_spec//specs-go:go_default_library",
"@org_golang_x_sys//unix:go_default_library",
],
)
diff --git a/runsc/cgroup/BUILD b/runsc/cgroup/BUILD
index 7e34a284a..37f4253ba 100644
--- a/runsc/cgroup/BUILD
+++ b/runsc/cgroup/BUILD
@@ -10,7 +10,7 @@ go_library(
"//pkg/cleanup",
"//pkg/log",
"@com_github_cenkalti_backoff//:go_default_library",
- "@com_github_opencontainers_runtime-spec//specs-go:go_default_library",
+ "@com_github_opencontainers_runtime_spec//specs-go:go_default_library",
],
)
@@ -22,6 +22,6 @@ go_test(
tags = ["local"],
deps = [
"//pkg/test/testutil",
- "@com_github_opencontainers_runtime-spec//specs-go:go_default_library",
+ "@com_github_opencontainers_runtime_spec//specs-go:go_default_library",
],
)
diff --git a/runsc/cmd/BUILD b/runsc/cmd/BUILD
index dae9b3b3e..1b5178dd5 100644
--- a/runsc/cmd/BUILD
+++ b/runsc/cmd/BUILD
@@ -58,7 +58,7 @@ go_library(
"//runsc/fsgofer/filter",
"//runsc/specutils",
"@com_github_google_subcommands//:go_default_library",
- "@com_github_opencontainers_runtime-spec//specs-go:go_default_library",
+ "@com_github_opencontainers_runtime_spec//specs-go:go_default_library",
"@com_github_syndtr_gocapability//capability:go_default_library",
"@org_golang_x_sys//unix:go_default_library",
],
@@ -87,9 +87,9 @@ go_test(
"//runsc/boot",
"//runsc/container",
"//runsc/specutils",
- "@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",
+ "@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",
"@com_github_syndtr_gocapability//capability:go_default_library",
],
)
diff --git a/runsc/container/BUILD b/runsc/container/BUILD
index 49cfb0837..9a9ee7e2a 100644
--- a/runsc/container/BUILD
+++ b/runsc/container/BUILD
@@ -27,7 +27,7 @@ go_library(
"//runsc/specutils",
"@com_github_cenkalti_backoff//:go_default_library",
"@com_github_gofrs_flock//:go_default_library",
- "@com_github_opencontainers_runtime-spec//specs-go:go_default_library",
+ "@com_github_opencontainers_runtime_spec//specs-go:go_default_library",
],
)
@@ -68,7 +68,7 @@ go_test(
"//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",
+ "@com_github_opencontainers_runtime_spec//specs-go:go_default_library",
"@org_golang_x_sys//unix:go_default_library",
],
)
diff --git a/runsc/sandbox/BUILD b/runsc/sandbox/BUILD
index 035dcd3e3..2b9d4549d 100644
--- a/runsc/sandbox/BUILD
+++ b/runsc/sandbox/BUILD
@@ -29,7 +29,7 @@ go_library(
"//runsc/console",
"//runsc/specutils",
"@com_github_cenkalti_backoff//:go_default_library",
- "@com_github_opencontainers_runtime-spec//specs-go:go_default_library",
+ "@com_github_opencontainers_runtime_spec//specs-go:go_default_library",
"@com_github_syndtr_gocapability//capability:go_default_library",
"@com_github_vishvananda_netlink//:go_default_library",
"@org_golang_x_sys//unix:go_default_library",
diff --git a/runsc/specutils/BUILD b/runsc/specutils/BUILD
index 62d4f5113..43851a22f 100644
--- a/runsc/specutils/BUILD
+++ b/runsc/specutils/BUILD
@@ -18,7 +18,7 @@ go_library(
"//pkg/sentry/kernel/auth",
"@com_github_cenkalti_backoff//:go_default_library",
"@com_github_mohae_deepcopy//:go_default_library",
- "@com_github_opencontainers_runtime-spec//specs-go:go_default_library",
+ "@com_github_opencontainers_runtime_spec//specs-go:go_default_library",
"@com_github_syndtr_gocapability//capability:go_default_library",
"@org_golang_x_sys//unix:go_default_library",
],
@@ -29,5 +29,5 @@ go_test(
size = "small",
srcs = ["specutils_test.go"],
library = ":specutils",
- deps = ["@com_github_opencontainers_runtime-spec//specs-go:go_default_library"],
+ deps = ["@com_github_opencontainers_runtime_spec//specs-go:go_default_library"],
)
diff --git a/scripts/benchmark.sh b/scripts/benchmark.sh
index e0f6df438..c49f988b8 100755
--- a/scripts/benchmark.sh
+++ b/scripts/benchmark.sh
@@ -16,30 +16,15 @@
source $(dirname $0)/common.sh
-# gcloud may be installed as a "snap". If it is, include it in PATH.
-declare -r snap="/snap/bin"
-if [[ -d "${snap}" ]]; then
- export PATH="${PATH}:${snap}"
-fi
-
-# Make sure we can find gcloud and exit if not.
-which gcloud
+make load-all-images
-# Exporting for subprocesses as GCP APIs and tools check this environmental
-# variable for authentication.
-export GOOGLE_APPLICATION_CREDENTIALS="${KOKORO_KEYSTORE_DIR}/${GCLOUD_CREDENTIALS}"
-
-gcloud auth activate-service-account \
- --key-file "${GOOGLE_APPLICATION_CREDENTIALS}"
+if [[ -z "${1:-}" ]]; then
+ target=$(query "attr(tags, manual, tests(//test/benchmarks/...))")
+else
+ target="$1"
+fi
-gcloud config set project ${PROJECT}
-gcloud config set compute/zone ${ZONE}
+install_runsc_for_benchmarks benchmark
-bazel run //benchmarks:benchmarks -- \
- --verbose \
- run-gcp \
- "(startup|absl)" \
- --internal \
- --runtime=runc \
- --runtime=runsc \
- --installers=head
+echo $target
+benchmark_runsc $target "${@:2}"
diff --git a/scripts/common.sh b/scripts/common.sh
index 3ca699e4a..36158654f 100755
--- a/scripts/common.sh
+++ b/scripts/common.sh
@@ -42,6 +42,15 @@ function test_runsc() {
test --test_arg=--runtime=${RUNTIME} "$@"
}
+function benchmark_runsc() {
+ test_runsc -c opt \
+ --nocache_test_results \
+ --test_arg=-test.bench=. \
+ --test_arg=-test.benchmem \
+ --jobs=1 \
+ "$@"
+}
+
function install_runsc_for_test() {
local -r test_name=$1
shift
@@ -63,6 +72,24 @@ function install_runsc_for_test() {
"$@"
}
+function install_runsc_for_benchmarks() {
+ local -r test_name=$1
+ shift
+ if [[ -z "${test_name}" ]]; then
+ echo "Missing mandatory test name"
+ exit 1
+ fi
+
+ # Add test to the name, so it doesn't conflict with other runtimes.
+ set_runtime $(find_branch_name)_"${test_name}"
+
+ # ${RUNSC_TEST_NAME} is set by tests (see dockerutil) to pass the test name
+ # down to the runtime.
+ install_runsc "${RUNTIME}" \
+ --TESTONLY-test-name-env=RUNSC_TEST_NAME \
+ "$@"
+}
+
# Installs the runsc with given runtime name. set_runtime must have been called
# to set runtime and logs location.
function install_runsc() {
diff --git a/scripts/common_build.sh b/scripts/common_build.sh
index 0d9a191b5..f4210a3f3 100755
--- a/scripts/common_build.sh
+++ b/scripts/common_build.sh
@@ -64,7 +64,7 @@ function run_as_root() {
}
function query() {
- QUERY_RESULT=$(bazel query "$@")
+ bazel query "$@"
}
function collect_logs() {
diff --git a/scripts/packetdrill_tests.sh b/scripts/packetdrill_tests.sh
index 727503bce..1a8181ac8 100755
--- a/scripts/packetdrill_tests.sh
+++ b/scripts/packetdrill_tests.sh
@@ -19,5 +19,5 @@ source $(dirname $0)/common.sh
make load-packetdrill
install_runsc_for_test runsc-d
-query "attr(tags, manual, tests(//test/packetdrill/...))"
+QUERY_RESULT=$(query "attr(tags, manual, tests(//test/packetdrill/...))")
test_runsc $QUERY_RESULT
diff --git a/scripts/packetimpact_tests.sh b/scripts/packetimpact_tests.sh
index 51c11f23f..77fb84bc3 100755
--- a/scripts/packetimpact_tests.sh
+++ b/scripts/packetimpact_tests.sh
@@ -19,5 +19,5 @@ source $(dirname $0)/common.sh
make load-packetimpact
install_runsc_for_test runsc-d
-query "attr(tags, packetimpact, tests(//test/packetimpact/...))"
+QUERY_RESULT=$(query "attr(tags, packetimpact, tests(//test/packetimpact/...))")
test_runsc $QUERY_RESULT
diff --git a/scripts/root_tests.sh b/scripts/root_tests.sh
index d629bf2aa..3eb735e62 100755
--- a/scripts/root_tests.sh
+++ b/scripts/root_tests.sh
@@ -17,15 +17,8 @@
source $(dirname $0)/common.sh
make load-all-images
-
-# 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
+CONTAINERD_VERSION=1.3.4 make sudo TARGETS="tools/installers:containerd"
+make sudo TARGETS="tools/installers:shim"
# Run the tests that require root.
install_runsc_for_test root
diff --git a/scripts/runtime_tests.sh b/scripts/runtime_tests.sh
index 350a59f7c..bb892a683 100755
--- a/scripts/runtime_tests.sh
+++ b/scripts/runtime_tests.sh
@@ -23,4 +23,4 @@ if [ ! -v RUNTIME_TEST_NAME ]; then
fi
install_runsc_for_test runtimes
-test_runsc "//test/runtimes:${RUNTIME_TEST_NAME}_test"
+test_runsc "//test/runtimes:${RUNTIME_TEST_NAME}"
diff --git a/shim/v1/BUILD b/shim/v1/BUILD
index 3a863ecbb..7b837630c 100644
--- a/shim/v1/BUILD
+++ b/shim/v1/BUILD
@@ -6,28 +6,26 @@ package(licenses = ["notice"])
go_binary(
name = "gvisor-containerd-shim",
srcs = [
+ "api.go",
"config.go",
"main.go",
],
- pure = True,
+ static = True,
visibility = [
"//visibility:public",
],
deps = [
"//pkg/shim/runsc",
"//pkg/shim/v1/shim",
- "//pkg/shim/v2",
"@com_github_burntsushi_toml//:go_default_library",
"@com_github_containerd_containerd//events:go_default_library",
"@com_github_containerd_containerd//namespaces:go_default_library",
- "@com_github_containerd_containerd//runtime/v1/linux/proc:go_default_library",
- "@com_github_containerd_containerd//runtime/v1/shim:go_default_library",
"@com_github_containerd_containerd//runtime/v1/shim/v1:go_default_library",
- "@com_github_containerd_containerd//runtime/v2/shim:go_default_library",
+ "@com_github_containerd_containerd//sys:go_default_library",
+ "@com_github_containerd_containerd//sys/reaper:go_default_library",
"@com_github_containerd_ttrpc//:go_default_library",
"@com_github_containerd_typeurl//:go_default_library",
"@com_github_gogo_protobuf//types:go_default_library",
- "@com_github_opencontainers_runc//libcontainer/system:go_default_library",
"@org_golang_x_sys//unix:go_default_library",
],
)
diff --git a/shim/v1/README.md b/shim/v1/README.md
index fcdf3ad77..7aa4513a1 100644
--- a/shim/v1/README.md
+++ b/shim/v1/README.md
@@ -29,15 +29,15 @@ sudo systemctl restart containerd
## Shim Confguration
-The shim configuration is stored in `/etc/containerd/runsc.toml`. The
+The shim configuration is stored in `/etc/containerd/runsc.toml`. The
configuration file supports two values.
-* `runc_shim`: The path to the runc shim. This is used by
- `gvisor-containerd-shim` to run standard containers.
+* `runc_shim`: The path to the runc shim. This is used by
+ `gvisor-containerd-shim` to run standard containers.
-* `runsc_config`: This is a set of key/value pairs that are converted into
- `runsc` command line flags. You can learn more about which flags are available
- by running `runsc flags`.
+* `runsc_config`: This is a set of key/value pairs that are converted into
+ `runsc` command line flags. You can learn more about which flags are
+ available by running `runsc flags`.
For example, a configuration might look as follows:
@@ -46,5 +46,5 @@ runc_shim = "/usr/local/bin/containerd-shim"
[runsc_config]
platform = "kvm"
debug = true
-debug-log = /var/log/%ID%/gvisor.log
+debug-log = /var/log/%ID%/gvisor/
```
diff --git a/shim/v1/api.go b/shim/v1/api.go
new file mode 100644
index 000000000..2444d23f1
--- /dev/null
+++ b/shim/v1/api.go
@@ -0,0 +1,24 @@
+// Copyright 2018 The containerd Authors.
+// 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
+//
+// https://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 main
+
+import (
+ shim "github.com/containerd/containerd/runtime/v1/shim/v1"
+)
+
+type KillRequest = shim.KillRequest
+
+var registerShimService = shim.RegisterShimService
diff --git a/shim/v1/main.go b/shim/v1/main.go
index 43deee858..3159923af 100644
--- a/shim/v1/main.go
+++ b/shim/v1/main.go
@@ -32,13 +32,11 @@ import (
"github.com/containerd/containerd/events"
"github.com/containerd/containerd/namespaces"
- "github.com/containerd/containerd/runtime/v1/linux/proc"
- containerdshim "github.com/containerd/containerd/runtime/v1/shim"
- shimapi "github.com/containerd/containerd/runtime/v1/shim/v1"
+ "github.com/containerd/containerd/sys"
+ "github.com/containerd/containerd/sys/reaper"
"github.com/containerd/ttrpc"
"github.com/containerd/typeurl"
- ptypes "github.com/gogo/protobuf/types"
- "github.com/opencontainers/runc/libcontainer/system"
+ "github.com/gogo/protobuf/types"
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/shim/runsc"
@@ -56,17 +54,17 @@ var (
shimConfigFlag string
)
+// Containerd defaults to runc, unless another runtime is explicitly specified.
+// We keep the same default to make the default behavior consistent.
+const defaultRoot = "/run/containerd/runc"
+
func init() {
flag.BoolVar(&debugFlag, "debug", false, "enable debug output in logs")
flag.StringVar(&namespaceFlag, "namespace", "", "namespace that owns the shim")
flag.StringVar(&socketFlag, "socket", "", "abstract socket path to serve")
flag.StringVar(&addressFlag, "address", "", "grpc address back to main containerd")
flag.StringVar(&workdirFlag, "workdir", "", "path used to storge large temporary data")
-
- // Containerd default to runc, unless another runtime is explicitly
- // specified. We keep the same default to make the default behavior
- // consistent.
- flag.StringVar(&runtimeRootFlag, "runtime-root", proc.RuncRoot, "root directory for the runtime")
+ flag.StringVar(&runtimeRootFlag, "runtime-root", defaultRoot, "root directory for the runtime")
// Currently, the `containerd publish` utility is embedded in the
// daemon binary. The daemon invokes `containerd-shim
@@ -148,7 +146,7 @@ func executeShim() error {
if err != nil {
return err
}
- shimapi.RegisterShimService(server, sv)
+ registerShimService(server, sv)
if err := serve(server, socketFlag); err != nil {
return err
}
@@ -191,10 +189,10 @@ func setupSignals() (chan os.Signal, error) {
signal.Notify(signals, unix.SIGTERM, unix.SIGINT, unix.SIGCHLD, unix.SIGPIPE)
// make sure runc is setup to use the monitor for waiting on processes.
// TODO(random-liu): Move shim/reaper.go to a separate package.
- runsc.Monitor = containerdshim.Default
+ runsc.Monitor = reaper.Default
// Set the shim as the subreaper for all orphaned processes created by
// the container.
- if err := system.SetSubreaper(1); err != nil {
+ if err := unix.Prctl(unix.PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0); err != nil {
return nil, err
}
return signals, nil
@@ -213,21 +211,21 @@ func handleSignals(signals chan os.Signal, server *ttrpc.Server, sv *shim.Servic
case s := <-signals:
switch s {
case unix.SIGCHLD:
- if err := containerdshim.Reap(); err != nil {
- log.Printf("reap exit status: %v")
+ if _, err := sys.Reap(false); err != nil {
+ log.Printf("reap error: %v", err)
}
case unix.SIGTERM, unix.SIGINT:
go termOnce.Do(func() {
ctx := context.TODO()
if err := server.Shutdown(ctx); err != nil {
- log.Printf("failed to shutdown server: %v")
+ log.Printf("failed to shutdown server: %v", err)
}
// Ensure our child is dead if any.
- sv.Kill(ctx, &shimapi.KillRequest{
+ sv.Kill(ctx, &KillRequest{
Signal: uint32(syscall.SIGKILL),
All: true,
})
- sv.Delete(context.Background(), &ptypes.Empty{})
+ sv.Delete(context.Background(), &types.Empty{})
close(done)
})
case unix.SIGPIPE:
@@ -252,11 +250,11 @@ func (l *remoteEventsPublisher) Publish(ctx context.Context, topic string, event
}
cmd := exec.CommandContext(ctx, containerdBinaryFlag, "--address", l.address, "publish", "--topic", topic, "--namespace", ns)
cmd.Stdin = bytes.NewReader(data)
- c, err := containerdshim.Default.Start(cmd)
+ c, err := reaper.Default.Start(cmd)
if err != nil {
return err
}
- status, err := containerdshim.Default.Wait(cmd, c)
+ status, err := reaper.Default.Wait(cmd, c)
if err != nil {
return fmt.Errorf("failed to publish event: %w", err)
}
diff --git a/shim/v2/BUILD b/shim/v2/BUILD
index 1e1947dab..ae4705935 100644
--- a/shim/v2/BUILD
+++ b/shim/v2/BUILD
@@ -1,4 +1,4 @@
-load("//tools:defs.bzl", "go_binary", "pkg_tar")
+load("//tools:defs.bzl", "go_binary")
load("//website:defs.bzl", "doc")
package(licenses = ["notice"])
@@ -8,15 +8,12 @@ go_binary(
srcs = [
"main.go",
],
- pure = True,
+ static = True,
visibility = [
"//visibility:public",
],
deps = [
- "//pkg/shim/runsc",
- "//pkg/shim/v1/shim",
"//pkg/shim/v2",
- "@com_github_burntsushi_toml//:go_default_library",
"@com_github_containerd_containerd//runtime/v2/shim:go_default_library",
],
)
diff --git a/shim/v2/README.md b/shim/v2/README.md
index 2fd625415..2aa7c21e3 100644
--- a/shim/v2/README.md
+++ b/shim/v2/README.md
@@ -51,17 +51,18 @@ In order to pick up the new configuration, you may need to restart containerd:
```shell
sudo systemctl restart containerd
```
+
## Shim Confguration
The shim configuration may carry the following options:
-* `shim_cgroup`: The cgroup to use for the shim itself.
-* `io_uid`: The UID to use for pipes.
-* `ui_gid`: The GID to use for pipes.
-* `binary_name`: The runtime binary name (defaults to `runsc`).
-* `root`: The root directory for the runtime.
-* `runsc_config`: A dictionary of key-value pairs that will be passed to the
- runtime as arguments.
+* `shim_cgroup`: The cgroup to use for the shim itself.
+* `io_uid`: The UID to use for pipes.
+* `ui_gid`: The GID to use for pipes.
+* `binary_name`: The runtime binary name (defaults to `runsc`).
+* `root`: The root directory for the runtime.
+* `runsc_config`: A dictionary of key-value pairs that will be passed to the
+ runtime as arguments.
### Example: Enable the KVM platform
diff --git a/shim/v2/main.go b/shim/v2/main.go
index 41c77394a..753871eea 100644
--- a/shim/v2/main.go
+++ b/shim/v2/main.go
@@ -18,9 +18,9 @@ package main
import (
"github.com/containerd/containerd/runtime/v2/shim"
- runsc "gvisor.dev/gvisor/pkg/shim/v2"
+ "gvisor.dev/gvisor/pkg/shim/v2"
)
func main() {
- shim.Run("io.containerd.runsc.v1", runsc.New)
+ shim.Run("io.containerd.runsc.v1", v2.New)
}
diff --git a/shim/v2/runtime-handler-shim-v2-quickstart.md b/shim/v2/runtime-handler-shim-v2-quickstart.md
index ca8336089..3b88ca74b 100644
--- a/shim/v2/runtime-handler-shim-v2-quickstart.md
+++ b/shim/v2/runtime-handler-shim-v2-quickstart.md
@@ -5,17 +5,21 @@ the containerd runtime handler support. This requires containerd 1.2 or later.
## Requirements
-- **runsc**: See the [gVisor documentation](https://github.com/google/gvisor) for information on how to install runsc.
-- **containerd**: See the [containerd website](https://containerd.io/) for information on how to install containerd.
+- **runsc**: See the [gVisor documentation](https://github.com/google/gvisor)
+ for information on how to install runsc.
+- **containerd**: See the [containerd website](https://containerd.io/) for
+ information on how to install containerd.
## Install
### Install containerd-shim-runsc-v1
-1. Build and install `containerd-shim-runsc-v1`.
+1. Build and install `containerd-shim-runsc-v1`.
<!-- TODO: Use a release once we have one available. -->
+
[embedmd]:# (../test/e2e/shim-install.sh shell /{ # Step 1\(dev\)/ /^}/)
+
```shell
{ # Step 1(dev): Build and install gvisor-containerd-shim and containerd-shim-runsc-v1
make
@@ -25,10 +29,11 @@ the containerd runtime handler support. This requires containerd 1.2 or later.
### Configure containerd
-1. Update `/etc/containerd/config.toml`. Make sure `containerd-shim-runsc-v1` is
- in `${PATH}`.
+1. Update `/etc/containerd/config.toml`. Make sure `containerd-shim-runsc-v1`
+ is in `${PATH}`.
[embedmd]:# (../test/e2e/runtime-handler-shim-v2/install.sh shell /{ # Step 1/ /^}/)
+
```shell
{ # Step 1: Create containerd config.toml
cat <<EOF | sudo tee /etc/containerd/config.toml
@@ -41,7 +46,7 @@ EOF
}
```
-2. Restart `containerd`
+1. Restart `containerd`
```shell
sudo systemctl restart containerd
@@ -53,9 +58,10 @@ You can run containers in gVisor via containerd's CRI.
### Install crictl
-1. Download and install the crictl binary:
+1. Download and install the crictl binary:
[embedmd]:# (../test/e2e/crictl-install.sh shell /{ # Step 1/ /^}/)
+
```shell
{ # Step 1: Download crictl
wget https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.13.0/crictl-v1.13.0-linux-amd64.tar.gz
@@ -64,9 +70,10 @@ sudo mv crictl /usr/local/bin
}
```
-2. Write the crictl configuration file
+1. Write the crictl configuration file
[embedmd]:# (../test/e2e/crictl-install.sh shell /{ # Step 2/ /^}/)
+
```shell
{ # Step 2: Configure crictl
cat <<EOF | sudo tee /etc/crictl.yaml
@@ -77,18 +84,20 @@ EOF
### Create the nginx Sandbox in gVisor
-1. Pull the nginx image
+1. Pull the nginx image
[embedmd]:# (../test/e2e/runtime-handler/usage.sh shell /{ # Step 1/ /^}/)
+
```shell
{ # Step 1: Pull the nginx image
sudo crictl pull nginx
}
```
-2. Create the sandbox creation request
+1. Create the sandbox creation request
[embedmd]:# (../test/e2e/runtime-handler/usage.sh shell /{ # Step 2/ /^EOF\n}/)
+
```shell
{ # Step 2: Create sandbox.json
cat <<EOF | tee sandbox.json
@@ -107,9 +116,10 @@ EOF
}
```
-3. Create the pod in gVisor
+1. Create the pod in gVisor
[embedmd]:# (../test/e2e/runtime-handler/usage.sh shell /{ # Step 3/ /^}/)
+
```shell
{ # Step 3: Create the sandbox
SANDBOX_ID=$(sudo crictl runp --runtime runsc sandbox.json)
@@ -118,9 +128,10 @@ SANDBOX_ID=$(sudo crictl runp --runtime runsc sandbox.json)
### Run the nginx Container in the Sandbox
-1. Create the nginx container creation request
+1. Create the nginx container creation request
[embedmd]:# (../test/e2e/run-container.sh shell /{ # Step 1/ /^EOF\n}/)
+
```shell
{ # Step 1: Create nginx container config
cat <<EOF | tee container.json
@@ -139,18 +150,20 @@ EOF
}
```
-2. Create the nginx container
+1. Create the nginx container
[embedmd]:# (../test/e2e/run-container.sh shell /{ # Step 2/ /^}/)
+
```shell
{ # Step 2: Create nginx container
CONTAINER_ID=$(sudo crictl create ${SANDBOX_ID} container.json sandbox.json)
}
```
-3. Start the nginx container
+1. Start the nginx container
[embedmd]:# (../test/e2e/run-container.sh shell /{ # Step 3/ /^}/)
+
```shell
{ # Step 3: Start nginx container
sudo crictl start ${CONTAINER_ID}
@@ -159,27 +172,30 @@ sudo crictl start ${CONTAINER_ID}
### Validate the container
-1. Inspect the created pod
+1. Inspect the created pod
[embedmd]:# (../test/e2e/validate.sh shell /{ # Step 1/ /^}/)
+
```shell
{ # Step 1: Inspect the pod
sudo crictl inspectp ${SANDBOX_ID}
}
```
-2. Inspect the nginx container
+1. Inspect the nginx container
[embedmd]:# (../test/e2e/validate.sh shell /{ # Step 2/ /^}/)
+
```shell
{ # Step 2: Inspect the container
sudo crictl inspect ${CONTAINER_ID}
}
```
-3. Verify that nginx is running in gVisor
+1. Verify that nginx is running in gVisor
[embedmd]:# (../test/e2e/validate.sh shell /{ # Step 3/ /^}/)
+
```shell
{ # Step 3: Check dmesg
sudo crictl exec ${CONTAINER_ID} dmesg | grep -i gvisor
@@ -188,9 +204,10 @@ sudo crictl exec ${CONTAINER_ID} dmesg | grep -i gvisor
### Set up the Kubernetes Runtime Class
-1. Install the Runtime Class for gVisor
+1. Install the Runtime Class for gVisor
[embedmd]:# (../test/e2e/runtimeclass-install.sh shell /{ # Step 1/ /^}/)
+
```shell
{ # Step 1: Install a RuntimeClass
cat <<EOF | kubectl apply -f -
@@ -203,9 +220,10 @@ EOF
}
```
-2. Create a Pod with the gVisor Runtime Class
+1. Create a Pod with the gVisor Runtime Class
[embedmd]:# (../test/e2e/runtimeclass-install.sh shell /{ # Step 2/ /^}/)
+
```shell
{ # Step 2: Create a pod
cat <<EOF | kubectl apply -f -
@@ -222,9 +240,10 @@ EOF
}
```
-3. Verify that the Pod is running
+1. Verify that the Pod is running
[embedmd]:# (../test/e2e/runtimeclass-install.sh shell /{ # Step 3/ /^}/)
+
```shell
{ # Step 3: Get the pod
kubectl get pod nginx-gvisor -o wide
diff --git a/test/benchmarks/README.md b/test/benchmarks/README.md
new file mode 100644
index 000000000..9ff602cf1
--- /dev/null
+++ b/test/benchmarks/README.md
@@ -0,0 +1,118 @@
+# Benchmark tools
+
+This package and subpackages are for running macro benchmarks on `runsc`. They
+are meant to replace the previous //benchmarks benchmark-tools written in
+python.
+
+Benchmarks are meant to look like regular golang benchmarks using the testing.B
+library.
+
+## Setup
+
+To run benchmarks you will need:
+
+* Docker installed (17.09.0 or greater).
+
+The easiest way to run benchmarks is to use the script at
+//scripts/benchmark.sh.
+
+If not using the script, you will need:
+
+* `runsc` configured with docker
+
+Note: benchmarks call the runtime by name. If docker can run it with
+`--runtime=` flag, these tools should work.
+
+## Running benchmarks
+
+The easiest way to run is with the script at //scripts/benchmarks.sh. The script
+will run all benchmarks under //test/benchmarks if a target is not provided.
+
+```bash
+./script/benchmarks.sh //path/to/target
+```
+
+If you want to run benchmarks manually:
+
+* Run `make load-all-images` from `//`
+* Run with:
+
+```bash
+bazel test --test_arg=--runtime=RUNTIME -c opt --test_output=streamed --test_timeout=600 --test_arg=-test.bench=. --nocache_test_results //path/to/target
+```
+
+## Writing benchmarks
+
+Benchmarks consist of docker images as Dockerfiles and golang testing.B
+benchmarks.
+
+### Dockerfiles:
+
+* Are stored at //images.
+* New Dockerfiles go in an appropriately named directory at
+ `//images/benchmarks/my-cool-dockerfile`.
+* Dockerfiles for benchmarks should:
+ * Use explicitly versioned packages.
+ * Not use ENV and CMD statements...it is easy to add these in the API.
+* Note: A common pattern for getting access to a tmpfs mount is to copy files
+ there after container start. See: //test/benchmarks/build/bazel_test.go. You
+ can also make your own with `RunOpts.Mounts`.
+
+### testing.B packages
+
+In general, benchmarks should look like this:
+
+```golang
+
+var h harness.Harness
+
+func BenchmarkMyCoolOne(b *testing.B) {
+ machine, err := h.GetMachine()
+ // check err
+
+ ctx := context.Background()
+ container := machine.GetContainer(ctx, b)
+ defer container.CleanUp(ctx)
+
+ b.ResetTimer()
+
+ //Respect b.N.
+ for i := 0; i < b.N; i++ {
+ out, err := container.Run(ctx, dockerutil.RunOpts{
+ Image: "benchmarks/my-cool-image",
+ Env: []string{"MY_VAR=awesome"},
+ other options...see dockerutil
+ }, "sh", "-c", "echo MY_VAR" ...)
+ //check err
+ b.StopTimer()
+
+ // Do parsing and reporting outside of the timer.
+ number := parseMyMetric(out)
+ b.ReportMetric(number, "my-cool-custom-metric")
+
+ b.StartTimer()
+ }
+}
+
+func TestMain(m *testing.M) {
+ h.Init()
+ os.Exit(m.Run())
+}
+```
+
+Some notes on the above:
+
+* The harness is initiated in the TestMain method and made global to test
+ module. The harness will handle any presetup that needs to happen with
+ flags, remote virtual machines (eventually), and other services.
+* Respect `b.N` in that users of the benchmark may want to "run for an hour"
+ or something of the sort.
+* Use the `b.ReportMetric` method to report custom metrics.
+* Set the timer if time is useful for reporting. There isn't a way to turn off
+ default metrics in testing.B (B/op, allocs/op, ns/op).
+* Take a look at dockerutil at //pkg/test/dockerutil to see all methods
+ available from containers. The API is based on the "official"
+ [docker API for golang](https://pkg.go.dev/mod/github.com/docker/docker).
+* `harness.GetMachine` marks how many machines this tests needs. If you have a
+ client and server and to mark them as multiple machines, call it
+ `GetMachine` twice.
diff --git a/test/benchmarks/fs/BUILD b/test/benchmarks/fs/BUILD
new file mode 100644
index 000000000..606331895
--- /dev/null
+++ b/test/benchmarks/fs/BUILD
@@ -0,0 +1,24 @@
+load("//tools:defs.bzl", "go_library", "go_test")
+
+package(licenses = ["notice"])
+
+go_library(
+ name = "fs",
+ srcs = ["fs.go"],
+)
+
+go_test(
+ name = "fs_test",
+ size = "large",
+ srcs = ["bazel_test.go"],
+ library = ":fs",
+ tags = [
+ # Requires docker and runsc to be configured before test runs.
+ "local",
+ "manual",
+ ],
+ deps = [
+ "//pkg/test/dockerutil",
+ "//test/benchmarks/harness",
+ ],
+)
diff --git a/test/benchmarks/fs/bazel_test.go b/test/benchmarks/fs/bazel_test.go
new file mode 100644
index 000000000..aabcdbd87
--- /dev/null
+++ b/test/benchmarks/fs/bazel_test.go
@@ -0,0 +1,103 @@
+// Copyright 2020 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 fs
+
+import (
+ "context"
+ "os"
+ "strings"
+ "testing"
+
+ "gvisor.dev/gvisor/pkg/test/dockerutil"
+ "gvisor.dev/gvisor/test/benchmarks/harness"
+)
+
+var h harness.Harness
+
+// Note: CleanCache versions of this test require running with root permissions.
+func BenchmarkABSL(b *testing.B) {
+ // Get a machine from the Harness on which to run.
+ machine, err := h.GetMachine()
+ if err != nil {
+ b.Fatalf("failed to get machine: %v", err)
+ }
+
+ // Dimensions here are clean/dirty cache (do or don't drop caches)
+ // and if the mount on which we are compiling is a tmpfs/bind mount.
+ benchmarks := []struct {
+ name string
+ clearCache bool // clearCache drops caches before running.
+ tmpfs bool // tmpfs will run compilation on a tmpfs.
+ }{
+ {name: "CleanCache", clearCache: true, tmpfs: false},
+ {name: "DirtyCache", clearCache: false, tmpfs: false},
+ {name: "CleanCacheTmpfs", clearCache: true, tmpfs: true},
+ {name: "DirtyCacheTmpfs", clearCache: false, tmpfs: true},
+ }
+ for _, bm := range benchmarks {
+ b.Run(bm.name, func(b *testing.B) {
+ // Grab a container.
+ ctx := context.Background()
+ container := machine.GetContainer(ctx, b)
+ defer container.CleanUp(ctx)
+
+ workdir := "/abseil-cpp"
+
+ // Start a container.
+ if err := container.Spawn(ctx, dockerutil.RunOpts{
+ Image: "benchmarks/absl",
+ }, "sleep", "1000"); err != nil {
+ b.Fatalf("run failed with: %v", err)
+ }
+
+ // If we are running on a tmpfs, copy to /tmp which is a tmpfs.
+ if bm.tmpfs {
+ if _, err := container.Exec(ctx, dockerutil.ExecOpts{},
+ "cp", "-r", "/abseil-cpp", "/tmp/."); err != nil {
+ b.Fatal("failed to copy directory: %v", err)
+ }
+ workdir = "/tmp" + workdir
+ }
+
+ // Drop Caches.
+ if bm.clearCache {
+ if out, err := machine.RunCommand("/bin/sh -c sync; echo 3 > /proc/sys/vm/drop_caches"); err != nil {
+ b.Fatalf("failed to drop caches: %v %s", err, out)
+ }
+ }
+
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ got, err := container.Exec(ctx, dockerutil.ExecOpts{
+ WorkDir: workdir,
+ }, "bazel", "build", "-c", "opt", "absl/base/...")
+ if err != nil {
+ b.Fatalf("build failed with: %v", err)
+ }
+ b.StopTimer()
+
+ want := "Build completed successfully"
+ if !strings.Contains(got, want) {
+ b.Fatalf("string %s not in: %s", want, got)
+ }
+ b.StartTimer()
+ }
+ })
+ }
+}
+
+func TestMain(m *testing.M) {
+ h.Init()
+ os.Exit(m.Run())
+}
diff --git a/test/benchmarks/fs/fs.go b/test/benchmarks/fs/fs.go
new file mode 100644
index 000000000..27eb6c56a
--- /dev/null
+++ b/test/benchmarks/fs/fs.go
@@ -0,0 +1,16 @@
+// Copyright 2020 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 fs holds benchmarks around filesystem performance.
+package fs
diff --git a/test/benchmarks/harness/BUILD b/test/benchmarks/harness/BUILD
new file mode 100644
index 000000000..c2e316709
--- /dev/null
+++ b/test/benchmarks/harness/BUILD
@@ -0,0 +1,18 @@
+load("//tools:defs.bzl", "go_library")
+
+package(licenses = ["notice"])
+
+go_library(
+ name = "harness",
+ testonly = 1,
+ srcs = [
+ "harness.go",
+ "machine.go",
+ "util.go",
+ ],
+ visibility = ["//:sandbox"],
+ deps = [
+ "//pkg/test/dockerutil",
+ "//pkg/test/testutil",
+ ],
+)
diff --git a/test/benchmarks/harness/harness.go b/test/benchmarks/harness/harness.go
new file mode 100644
index 000000000..68bd7b4cf
--- /dev/null
+++ b/test/benchmarks/harness/harness.go
@@ -0,0 +1,38 @@
+// Copyright 2020 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 harness holds utility code for running benchmarks on Docker.
+package harness
+
+import (
+ "flag"
+
+ "gvisor.dev/gvisor/pkg/test/dockerutil"
+)
+
+// Harness is a handle for managing state in benchmark runs.
+type Harness struct {
+}
+
+// Init performs any harness initilialization before runs.
+func (h *Harness) Init() error {
+ flag.Parse()
+ dockerutil.EnsureSupportedDockerVersion()
+ return nil
+}
+
+// GetMachine returns this run's implementation of machine.
+func (h *Harness) GetMachine() (Machine, error) {
+ return &localMachine{}, nil
+}
diff --git a/test/benchmarks/harness/machine.go b/test/benchmarks/harness/machine.go
new file mode 100644
index 000000000..032b387fc
--- /dev/null
+++ b/test/benchmarks/harness/machine.go
@@ -0,0 +1,64 @@
+// Copyright 2020 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 harness
+
+import (
+ "context"
+ "net"
+ "os/exec"
+
+ "gvisor.dev/gvisor/pkg/test/dockerutil"
+ "gvisor.dev/gvisor/pkg/test/testutil"
+)
+
+// Machine describes a real machine for use in benchmarks.
+type Machine interface {
+ // GetContainer gets a container from the machine,
+ GetContainer(ctx context.Context, log testutil.Logger) *dockerutil.Container
+
+ // RunCommand runs cmd on this machine.
+ RunCommand(cmd string, args ...string) (string, error)
+
+ // Returns IP Address for the machine.
+ IPAddress() (net.IP, error)
+}
+
+// localMachine describes this machine.
+type localMachine struct {
+}
+
+// GetContainer implements Machine.GetContainer for localMachine.
+func (l *localMachine) GetContainer(ctx context.Context, logger testutil.Logger) *dockerutil.Container {
+ return dockerutil.MakeContainer(ctx, logger)
+}
+
+// RunCommand implements Machine.RunCommand for localMachine.
+func (l *localMachine) RunCommand(cmd string, args ...string) (string, error) {
+ c := exec.Command(cmd, args...)
+ out, err := c.CombinedOutput()
+ return string(out), err
+}
+
+// IPAddress implements Machine.IPAddress.
+func (l *localMachine) IPAddress() (net.IP, error) {
+ conn, err := net.Dial("udp", "8.8.8.8:80")
+ if err != nil {
+ return nil, err
+ }
+ defer conn.Close()
+
+ addr := conn.LocalAddr().(*net.UDPAddr)
+ return addr.IP, nil
+}
diff --git a/test/benchmarks/harness/util.go b/test/benchmarks/harness/util.go
new file mode 100644
index 000000000..cc7de6426
--- /dev/null
+++ b/test/benchmarks/harness/util.go
@@ -0,0 +1,38 @@
+// Copyright 2020 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 harness
+
+import (
+ "context"
+ "fmt"
+ "net"
+
+ "gvisor.dev/gvisor/pkg/test/dockerutil"
+ "gvisor.dev/gvisor/pkg/test/testutil"
+)
+
+// WaitUntilServing grabs a container from `machine` and waits for a server at
+// IP:port.
+func WaitUntilServing(ctx context.Context, machine Machine, server net.IP, port int) error {
+ var logger testutil.DefaultLogger = "netcat"
+ netcat := machine.GetContainer(ctx, logger)
+ defer netcat.CleanUp(ctx)
+
+ cmd := fmt.Sprintf("while ! nc -zv %s %d; do true; done", server.String(), port)
+ _, err := netcat.Run(ctx, dockerutil.RunOpts{
+ Image: "packetdrill",
+ }, "sh", "-c", cmd)
+ return err
+}
diff --git a/test/benchmarks/network/BUILD b/test/benchmarks/network/BUILD
new file mode 100644
index 000000000..57328456d
--- /dev/null
+++ b/test/benchmarks/network/BUILD
@@ -0,0 +1,25 @@
+load("//tools:defs.bzl", "go_library", "go_test")
+
+package(licenses = ["notice"])
+
+go_library(
+ name = "network",
+ testonly = 1,
+ srcs = ["network.go"],
+)
+
+go_test(
+ name = "network_test",
+ size = "large",
+ srcs = ["iperf_test.go"],
+ library = ":network",
+ tags = [
+ # Requires docker and runsc to be configured before test runs.
+ "manual",
+ "local",
+ ],
+ deps = [
+ "//pkg/test/dockerutil",
+ "//test/benchmarks/harness",
+ ],
+)
diff --git a/test/benchmarks/network/iperf_test.go b/test/benchmarks/network/iperf_test.go
new file mode 100644
index 000000000..72e9c99a8
--- /dev/null
+++ b/test/benchmarks/network/iperf_test.go
@@ -0,0 +1,151 @@
+// Copyright 2020 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 network
+
+import (
+ "context"
+ "fmt"
+ "os"
+ "regexp"
+ "strconv"
+ "strings"
+ "testing"
+
+ "gvisor.dev/gvisor/pkg/test/dockerutil"
+ "gvisor.dev/gvisor/test/benchmarks/harness"
+)
+
+var h harness.Harness
+
+func BenchmarkIperf(b *testing.B) {
+
+ // Get two machines
+ clientMachine, err := h.GetMachine()
+ if err != nil {
+ b.Fatalf("failed to get machine: %v", err)
+ }
+
+ serverMachine, err := h.GetMachine()
+ if err != nil {
+ b.Fatalf("failed to get machine: %v", err)
+ }
+
+ for _, bm := range []struct {
+ name string
+ clientRuntime string
+ serverRuntime string
+ }{
+ // We are either measuring the server or the client. The other should be
+ // runc. e.g. Upload sees how fast the runtime under test uploads to a native
+ // server.
+ {name: "Upload", clientRuntime: dockerutil.Runtime(), serverRuntime: "runc"},
+ {name: "Download", clientRuntime: "runc", serverRuntime: dockerutil.Runtime()},
+ } {
+ b.Run(bm.name, func(b *testing.B) {
+
+ // Get a container from the server and set its runtime.
+ ctx := context.Background()
+ server := serverMachine.GetContainer(ctx, b)
+ defer server.CleanUp(ctx)
+ server.Runtime = bm.serverRuntime
+
+ // Get a container from the client and set its runtime.
+ client := clientMachine.GetContainer(ctx, b)
+ defer client.CleanUp(ctx)
+ client.Runtime = bm.clientRuntime
+
+ // iperf serves on port 5001 by default.
+ port := 5001
+
+ // Start the server.
+ if err := server.Spawn(ctx, dockerutil.RunOpts{
+ Image: "benchmarks/iperf",
+ Ports: []int{port},
+ }, "iperf", "-s"); err != nil {
+ b.Fatalf("failed to start server with: %v", err)
+ }
+
+ ip, err := serverMachine.IPAddress()
+ if err != nil {
+ b.Fatalf("failed to find server ip: %v", err)
+ }
+
+ servingPort, err := server.FindPort(ctx, port)
+ if err != nil {
+ b.Fatalf("failed to find port %d: %v", port, err)
+ }
+
+ // Make sure the server is up and serving before we run.
+ if err := harness.WaitUntilServing(ctx, clientMachine, ip, servingPort); err != nil {
+ b.Fatalf("failed to wait for server: %v", err)
+ }
+
+ // iperf report in Kb realtime
+ cmd := fmt.Sprintf("iperf -f K --realtime -c %s -p %d", ip.String(), servingPort)
+
+ // Run the client.
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ out, err := client.Run(ctx, dockerutil.RunOpts{
+ Image: "benchmarks/iperf",
+ }, strings.Split(cmd, " ")...)
+ if err != nil {
+ b.Fatalf("failed to run client: %v", err)
+ }
+ b.StopTimer()
+
+ // Parse bandwidth and report it.
+ bW, err := bandwidth(out)
+ if err != nil {
+ b.Fatalf("failed to parse bandwitdth from %s: %v", out, err)
+ }
+ b.ReportMetric(bW, "KBytes/sec")
+ b.StartTimer()
+ }
+ })
+ }
+}
+
+// bandwidth parses the Bandwidth number from an iperf report. A sample is below.
+func bandwidth(data string) (float64, error) {
+ re := regexp.MustCompile(`\[\s*\d+\][^\n]+\s+(\d+\.?\d*)\s+KBytes/sec`)
+ match := re.FindStringSubmatch(data)
+ if len(match) < 1 {
+ return 0, fmt.Errorf("failed get bandwidth: %s", data)
+ }
+ return strconv.ParseFloat(match[1], 64)
+}
+
+func TestParser(t *testing.T) {
+ sampleData := `
+------------------------------------------------------------
+Client connecting to 10.138.15.215, TCP port 32779
+TCP window size: 45.0 KByte (default)
+------------------------------------------------------------
+[ 3] local 10.138.15.216 port 32866 connected with 10.138.15.215 port 32779
+[ ID] Interval Transfer Bandwidth
+[ 3] 0.0-10.0 sec 459520 KBytes 45900 KBytes/sec
+`
+ bandwidth, err := bandwidth(sampleData)
+ if err != nil || bandwidth != 45900 {
+ t.Fatalf("failed with: %v and %f", err, bandwidth)
+ }
+
+}
+
+func TestMain(m *testing.M) {
+ h.Init()
+ os.Exit(m.Run())
+}
diff --git a/test/benchmarks/network/network.go b/test/benchmarks/network/network.go
new file mode 100644
index 000000000..f480b5bcd
--- /dev/null
+++ b/test/benchmarks/network/network.go
@@ -0,0 +1,16 @@
+// Copyright 2020 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 network holds benchmarks around raw network performance.
+package network
diff --git a/test/packetimpact/runner/packetimpact_test.go b/test/packetimpact/runner/packetimpact_test.go
index 9290d5112..397ca3ba5 100644
--- a/test/packetimpact/runner/packetimpact_test.go
+++ b/test/packetimpact/runner/packetimpact_test.go
@@ -283,8 +283,8 @@ func TestOne(t *testing.T) {
// will issue a RST. To prevent this IPtables can be used to filter out all
// incoming packets. The raw socket that packetimpact tests use will still see
// everything.
- if _, err := testbench.Exec(ctx, dockerutil.ExecOpts{}, "iptables", "-A", "INPUT", "-i", testNetDev, "-j", "DROP"); err != nil {
- t.Fatalf("unable to Exec iptables on container %s: %s", testbench.Name, err)
+ if logs, err := testbench.Exec(ctx, dockerutil.ExecOpts{}, "iptables", "-A", "INPUT", "-i", testNetDev, "-j", "DROP"); err != nil {
+ t.Fatalf("unable to Exec iptables on container %s: %s, logs from testbench:\n%s", testbench.Name, err, logs)
}
// FIXME(b/156449515): Some piece of the system has a race. The old
@@ -307,12 +307,12 @@ func TestOne(t *testing.T) {
"--device", testNetDev,
"--dut_type", *dutPlatform,
)
- _, err = testbench.Exec(ctx, dockerutil.ExecOpts{}, testArgs...)
+ logs, err := testbench.Exec(ctx, dockerutil.ExecOpts{}, testArgs...)
if !*expectFailure && err != nil {
- t.Fatal("test failed:", err)
+ t.Fatalf("test failed: %v, logs from testbench:\n%s", err, logs)
}
if *expectFailure && err == nil {
- t.Fatal("test failure expected but the test succeeded, enable the test and mark the corresponding bug as fixed")
+ t.Fatalf("test failure expected but the test succeeded, enable the test and mark the corresponding bug as fixed, logs from testbench:\n%s", logs)
}
}
diff --git a/test/packetimpact/testbench/BUILD b/test/packetimpact/testbench/BUILD
index d19ec07d4..5a0ee1367 100644
--- a/test/packetimpact/testbench/BUILD
+++ b/test/packetimpact/testbench/BUILD
@@ -23,8 +23,8 @@ go_library(
"//pkg/usermem",
"//test/packetimpact/netdevs",
"//test/packetimpact/proto:posix_server_go_proto",
- "@com_github_google_go-cmp//cmp:go_default_library",
- "@com_github_google_go-cmp//cmp/cmpopts:go_default_library",
+ "@com_github_google_go_cmp//cmp:go_default_library",
+ "@com_github_google_go_cmp//cmp/cmpopts:go_default_library",
"@com_github_mohae_deepcopy//:go_default_library",
"@org_golang_google_grpc//:go_default_library",
"@org_golang_google_grpc//keepalive:go_default_library",
diff --git a/test/packetimpact/testbench/testbench.go b/test/packetimpact/testbench/testbench.go
index d64f32a5b..6530036a8 100644
--- a/test/packetimpact/testbench/testbench.go
+++ b/test/packetimpact/testbench/testbench.go
@@ -31,23 +31,30 @@ var (
DUTType = ""
// Device is the local device on the test network.
Device = ""
+
// LocalIPv4 is the local IPv4 address on the test network.
LocalIPv4 = ""
+ // RemoteIPv4 is the DUT's IPv4 address on the test network.
+ RemoteIPv4 = ""
+ // IPv4PrefixLength is the network prefix length of the IPv4 test network.
+ IPv4PrefixLength = 0
+
// LocalIPv6 is the local IPv6 address on the test network.
LocalIPv6 = ""
+ // RemoteIPv6 is the DUT's IPv6 address on the test network.
+ RemoteIPv6 = ""
+
// LocalMAC is the local MAC address on the test network.
LocalMAC = ""
+ // RemoteMAC is the DUT's MAC address on the test network.
+ RemoteMAC = ""
+
// POSIXServerIP is the POSIX server's IP address on the control network.
POSIXServerIP = ""
// POSIXServerPort is the UDP port the POSIX server is bound to on the
// control network.
POSIXServerPort = 40000
- // RemoteIPv4 is the DUT's IPv4 address on the test network.
- RemoteIPv4 = ""
- // RemoteIPv6 is the DUT's IPv6 address on the test network.
- RemoteIPv6 = ""
- // RemoteMAC is the DUT's MAC address on the test network.
- RemoteMAC = ""
+
// RPCKeepalive is the gRPC keepalive.
RPCKeepalive = 10 * time.Second
// RPCTimeout is the gRPC timeout.
@@ -91,6 +98,12 @@ func genPseudoFlags() error {
LocalMAC = deviceInfo.MAC.String()
LocalIPv6 = deviceInfo.IPv6Addr.String()
+ if deviceInfo.IPv4Net != nil {
+ IPv4PrefixLength, _ = deviceInfo.IPv4Net.Mask.Size()
+ } else {
+ IPv4PrefixLength, _ = net.ParseIP(LocalIPv4).DefaultMask().Size()
+ }
+
return nil
}
diff --git a/test/packetimpact/tests/BUILD b/test/packetimpact/tests/BUILD
index 3ecbe83eb..3f538b5c6 100644
--- a/test/packetimpact/tests/BUILD
+++ b/test/packetimpact/tests/BUILD
@@ -27,8 +27,8 @@ packetimpact_go_test(
)
packetimpact_go_test(
- name = "udp_recv_multicast",
- srcs = ["udp_recv_multicast_test.go"],
+ name = "udp_recv_mcast_bcast",
+ srcs = ["udp_recv_mcast_bcast_test.go"],
# TODO(b/152813495): Fix netstack then remove the line below.
expect_netstack_failure = True,
deps = [
diff --git a/test/packetimpact/tests/udp_recv_multicast_test.go b/test/packetimpact/tests/udp_recv_mcast_bcast_test.go
index 77a9bfa1d..263a54291 100644
--- a/test/packetimpact/tests/udp_recv_multicast_test.go
+++ b/test/packetimpact/tests/udp_recv_mcast_bcast_test.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package udp_recv_multicast_test
+package udp_recv_mcast_bcast_test
import (
"flag"
@@ -28,13 +28,36 @@ func init() {
testbench.RegisterFlags(flag.CommandLine)
}
-func TestUDPRecvMulticast(t *testing.T) {
+func TestUDPRecvMulticastBroadcast(t *testing.T) {
dut := testbench.NewDUT(t)
defer dut.TearDown()
- boundFD, remotePort := dut.CreateBoundSocket(unix.SOCK_DGRAM, unix.IPPROTO_UDP, net.ParseIP("0.0.0.0"))
+ boundFD, remotePort := dut.CreateBoundSocket(unix.SOCK_DGRAM, unix.IPPROTO_UDP, net.IPv4(0, 0, 0, 0))
defer dut.Close(boundFD)
conn := testbench.NewUDPIPv4(t, testbench.UDP{DstPort: &remotePort}, testbench.UDP{SrcPort: &remotePort})
defer conn.Close()
- conn.SendIP(testbench.IPv4{DstAddr: testbench.Address(tcpip.Address(net.ParseIP("224.0.0.1").To4()))}, testbench.UDP{})
- dut.Recv(boundFD, 100, 0)
+
+ for _, bcastAddr := range []net.IP{
+ broadcastAddr(net.ParseIP(testbench.RemoteIPv4), net.CIDRMask(testbench.IPv4PrefixLength, 32)),
+ net.IPv4(255, 255, 255, 255),
+ net.IPv4(224, 0, 0, 1),
+ } {
+ payload := testbench.GenerateRandomPayload(t, 1<<10)
+ conn.SendIP(
+ testbench.IPv4{DstAddr: testbench.Address(tcpip.Address(bcastAddr.To4()))},
+ testbench.UDP{},
+ &testbench.Payload{Bytes: payload},
+ )
+ t.Logf("Receiving packet sent to address: %s", bcastAddr)
+ if got, want := string(dut.Recv(boundFD, int32(len(payload)), 0)), string(payload); got != want {
+ t.Errorf("received payload does not match sent payload got: %s, want: %s", got, want)
+ }
+ }
+}
+
+func broadcastAddr(ip net.IP, mask net.IPMask) net.IP {
+ ip4 := ip.To4()
+ for i := range ip4 {
+ ip4[i] |= ^mask[i]
+ }
+ return ip4
}
diff --git a/test/root/BUILD b/test/root/BUILD
index 1d19d1f5f..a9130b34f 100644
--- a/test/root/BUILD
+++ b/test/root/BUILD
@@ -41,7 +41,7 @@ go_test(
"//runsc/container",
"//runsc/specutils",
"@com_github_cenkalti_backoff//:go_default_library",
- "@com_github_opencontainers_runtime-spec//specs-go:go_default_library",
+ "@com_github_opencontainers_runtime_spec//specs-go:go_default_library",
"@com_github_syndtr_gocapability//capability:go_default_library",
"@org_golang_x_sys//unix:go_default_library",
],
diff --git a/test/runner/BUILD b/test/runner/BUILD
index 6833c9986..1f45a6922 100644
--- a/test/runner/BUILD
+++ b/test/runner/BUILD
@@ -16,7 +16,7 @@ go_binary(
"//runsc/specutils",
"//test/runner/gtest",
"//test/uds",
- "@com_github_opencontainers_runtime-spec//specs-go:go_default_library",
+ "@com_github_opencontainers_runtime_spec//specs-go:go_default_library",
"@org_golang_x_sys//unix:go_default_library",
],
)
diff --git a/test/runtimes/BUILD b/test/runtimes/BUILD
index 022de5ff7..f98d02e00 100644
--- a/test/runtimes/BUILD
+++ b/test/runtimes/BUILD
@@ -6,28 +6,33 @@ runtime_test(
name = "go1.12",
exclude_file = "exclude_go1.12.csv",
lang = "go",
+ shard_count = 5,
)
runtime_test(
name = "java11",
exclude_file = "exclude_java11.csv",
lang = "java",
+ shard_count = 10,
)
runtime_test(
name = "nodejs12.4.0",
exclude_file = "exclude_nodejs12.4.0.csv",
lang = "nodejs",
+ shard_count = 5,
)
runtime_test(
name = "php7.3.6",
exclude_file = "exclude_php7.3.6.csv",
lang = "php",
+ shard_count = 5,
)
runtime_test(
name = "python3.7.3",
exclude_file = "exclude_python3.7.3.csv",
lang = "python",
+ shard_count = 5,
)
diff --git a/test/runtimes/exclude_nodejs12.4.0.csv b/test/runtimes/exclude_nodejs12.4.0.csv
index 4ab4e2927..e7edfa0a5 100644
--- a/test/runtimes/exclude_nodejs12.4.0.csv
+++ b/test/runtimes/exclude_nodejs12.4.0.csv
@@ -9,6 +9,8 @@ fixtures/test-fs-stat-sync-overflow.js,,
internet/test-dgram-broadcast-multi-process.js,,
internet/test-dgram-multicast-multi-process.js,,
internet/test-dgram-multicast-set-interface-lo.js,,
+internet/test-doctool-versions.js,,
+internet/test-uv-threadpool-schedule.js,,
parallel/test-cluster-dgram-reuse.js,b/64024294,
parallel/test-dgram-bind-fd.js,b/132447356,
parallel/test-dgram-create-socket-handle-fd.js,b/132447238,
@@ -45,3 +47,4 @@ pseudo-tty/test-tty-window-size.js,,
pseudo-tty/test-tty-wrap.js,,
pummel/test-net-pingpong.js,,
pummel/test-vm-memleak.js,,
+tick-processor/test-tick-processor-builtin.js,,
diff --git a/test/runtimes/exclude_php7.3.6.csv b/test/runtimes/exclude_php7.3.6.csv
index 456bf7487..f3606bfe8 100644
--- a/test/runtimes/exclude_php7.3.6.csv
+++ b/test/runtimes/exclude_php7.3.6.csv
@@ -8,6 +8,9 @@ ext/mbstring/tests/bug77165.phpt,,
ext/mbstring/tests/bug77454.phpt,,
ext/mbstring/tests/mb_convert_encoding_leak.phpt,,
ext/mbstring/tests/mb_strrpos_encoding_3rd_param.phpt,,
+ext/session/tests/session_set_save_handler_class_018.phpt,,
+ext/session/tests/session_set_save_handler_iface_003.phpt,,
+ext/session/tests/session_set_save_handler_variation4.phpt,,
ext/standard/tests/file/filetype_variation.phpt,,
ext/standard/tests/file/fopen_variation19.phpt,,
ext/standard/tests/file/php_fd_wrapper_01.phpt,,
@@ -21,9 +24,12 @@ ext/standard/tests/file/symlink_link_linkinfo_is_link_variation8.phpt,,
ext/standard/tests/general_functions/escapeshellarg_bug71270.phpt,,
ext/standard/tests/general_functions/escapeshellcmd_bug71270.phpt,,
ext/standard/tests/network/bug20134.phpt,,
+ext/standard/tests/streams/stream_socket_sendto.phpt,,
+ext/standard/tests/strings/007.phpt,,
tests/output/stream_isatty_err.phpt,b/68720279,
tests/output/stream_isatty_in-err.phpt,b/68720282,
tests/output/stream_isatty_in-out-err.phpt,,
tests/output/stream_isatty_in-out.phpt,b/68720299,
tests/output/stream_isatty_out-err.phpt,b/68720311,
tests/output/stream_isatty_out.phpt,b/68720325,
+Zend/tests/concat_003.phpt,,
diff --git a/test/runtimes/proctor/go.go b/test/runtimes/proctor/go.go
index 3e2d5d8db..073c2959d 100644
--- a/test/runtimes/proctor/go.go
+++ b/test/runtimes/proctor/go.go
@@ -74,17 +74,26 @@ func (goRunner) ListTests() ([]string, error) {
return append(toolSlice, diskFiltered...), nil
}
-// TestCmd implements TestRunner.TestCmd.
-func (goRunner) TestCmd(test string) *exec.Cmd {
- // Check if test exists on disk by searching for file of the same name.
- // This will determine whether or not it is a Go test on disk.
- if strings.HasSuffix(test, ".go") {
- // Test has suffix ".go" which indicates a disk test, run it as such.
- cmd := exec.Command("go", "run", "run.go", "-v", "--", test)
+// TestCmds implements TestRunner.TestCmds.
+func (goRunner) TestCmds(tests []string) []*exec.Cmd {
+ var toolTests, onDiskTests []string
+ for _, test := range tests {
+ if strings.HasSuffix(test, ".go") {
+ onDiskTests = append(onDiskTests, test)
+ } else {
+ toolTests = append(toolTests, test)
+ }
+ }
+
+ var cmds []*exec.Cmd
+ if len(toolTests) > 0 {
+ cmds = append(cmds, exec.Command("go", "tool", "dist", "test", "-run", strings.Join(toolTests, "\\|")))
+ }
+ if len(onDiskTests) > 0 {
+ cmd := exec.Command("go", append([]string{"run", "run.go", "-v", "--"}, onDiskTests...)...)
cmd.Dir = goTestDir
- return cmd
+ cmds = append(cmds, cmd)
}
- // No ".go" suffix, run as a tool test.
- return exec.Command("go", "tool", "dist", "test", "-run", test)
+ return cmds
}
diff --git a/test/runtimes/proctor/java.go b/test/runtimes/proctor/java.go
index 8b362029d..737fbe23e 100644
--- a/test/runtimes/proctor/java.go
+++ b/test/runtimes/proctor/java.go
@@ -60,12 +60,14 @@ func (javaRunner) ListTests() ([]string, error) {
return testSlice, nil
}
-// TestCmd implements TestRunner.TestCmd.
-func (javaRunner) TestCmd(test string) *exec.Cmd {
- args := []string{
- "-noreport",
- "-dir:" + javaTestDir,
- test,
- }
- return exec.Command("jtreg", args...)
+// TestCmds implements TestRunner.TestCmds.
+func (javaRunner) TestCmds(tests []string) []*exec.Cmd {
+ args := append(
+ []string{
+ "-noreport",
+ "-dir:" + javaTestDir,
+ },
+ tests...,
+ )
+ return []*exec.Cmd{exec.Command("jtreg", args...)}
}
diff --git a/test/runtimes/proctor/nodejs.go b/test/runtimes/proctor/nodejs.go
index bd57db444..23d6edc72 100644
--- a/test/runtimes/proctor/nodejs.go
+++ b/test/runtimes/proctor/nodejs.go
@@ -39,8 +39,8 @@ func (nodejsRunner) ListTests() ([]string, error) {
return testSlice, nil
}
-// TestCmd implements TestRunner.TestCmd.
-func (nodejsRunner) TestCmd(test string) *exec.Cmd {
- args := []string{filepath.Join("tools", "test.py"), test}
- return exec.Command("/usr/bin/python", args...)
+// TestCmds implements TestRunner.TestCmds.
+func (nodejsRunner) TestCmds(tests []string) []*exec.Cmd {
+ args := append([]string{filepath.Join("tools", "test.py")}, tests...)
+ return []*exec.Cmd{exec.Command("/usr/bin/python", args...)}
}
diff --git a/test/runtimes/proctor/php.go b/test/runtimes/proctor/php.go
index 9115040e1..6a83d64e3 100644
--- a/test/runtimes/proctor/php.go
+++ b/test/runtimes/proctor/php.go
@@ -17,6 +17,7 @@ package main
import (
"os/exec"
"regexp"
+ "strings"
)
var phpTestRegEx = regexp.MustCompile(`^.+\.phpt$`)
@@ -35,8 +36,8 @@ func (phpRunner) ListTests() ([]string, error) {
return testSlice, nil
}
-// TestCmd implements TestRunner.TestCmd.
-func (phpRunner) TestCmd(test string) *exec.Cmd {
- args := []string{"test", "TESTS=" + test}
- return exec.Command("make", args...)
+// TestCmds implements TestRunner.TestCmds.
+func (phpRunner) TestCmds(tests []string) []*exec.Cmd {
+ args := []string{"test", "TESTS=" + strings.Join(tests, " ")}
+ return []*exec.Cmd{exec.Command("make", args...)}
}
diff --git a/test/runtimes/proctor/proctor.go b/test/runtimes/proctor/proctor.go
index b54abe434..9e0642424 100644
--- a/test/runtimes/proctor/proctor.go
+++ b/test/runtimes/proctor/proctor.go
@@ -25,6 +25,7 @@ import (
"os/signal"
"path/filepath"
"regexp"
+ "strings"
"syscall"
)
@@ -34,15 +35,18 @@ type TestRunner interface {
// ListTests returns a string slice of tests available to run.
ListTests() ([]string, error)
- // TestCmd returns an *exec.Cmd that will run the given test.
- TestCmd(test string) *exec.Cmd
+ // TestCmds returns a slice of *exec.Cmd that will run the given tests.
+ // There is no correlation between the number of exec.Cmds returned and the
+ // number of tests. It could return one command to run all tests or a few
+ // commands that collectively run all.
+ TestCmds(tests []string) []*exec.Cmd
}
var (
- runtime = flag.String("runtime", "", "name of runtime")
- list = flag.Bool("list", false, "list all available tests")
- testName = flag.String("test", "", "run a single test from the list of available tests")
- pause = flag.Bool("pause", false, "cause container to pause indefinitely, reaping any zombie children")
+ runtime = flag.String("runtime", "", "name of runtime")
+ list = flag.Bool("list", false, "list all available tests")
+ testNames = flag.String("tests", "", "run a subset of the available tests")
+ pause = flag.Bool("pause", false, "cause container to pause indefinitely, reaping any zombie children")
)
func main() {
@@ -75,18 +79,20 @@ func main() {
}
var tests []string
- if *testName == "" {
+ if *testNames == "" {
// Run every test.
tests, err = tr.ListTests()
if err != nil {
log.Fatalf("failed to get all tests: %v", err)
}
} else {
- // Run a single test.
- tests = []string{*testName}
+ // Run subset of test.
+ tests = strings.Split(*testNames, ",")
}
- for _, test := range tests {
- cmd := tr.TestCmd(test)
+
+ // Run tests.
+ cmds := tr.TestCmds(tests)
+ for _, cmd := range cmds {
cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
if err := cmd.Run(); err != nil {
log.Fatalf("FAIL: %v", err)
diff --git a/test/runtimes/proctor/python.go b/test/runtimes/proctor/python.go
index b9e0fbe6f..7c598801b 100644
--- a/test/runtimes/proctor/python.go
+++ b/test/runtimes/proctor/python.go
@@ -42,8 +42,8 @@ func (pythonRunner) ListTests() ([]string, error) {
return toolSlice, nil
}
-// TestCmd implements TestRunner.TestCmd.
-func (pythonRunner) TestCmd(test string) *exec.Cmd {
- args := []string{"-m", "test", test}
- return exec.Command("./python", args...)
+// TestCmds implements TestRunner.TestCmds.
+func (pythonRunner) TestCmds(tests []string) []*exec.Cmd {
+ args := append([]string{"-m", "test"}, tests...)
+ return []*exec.Cmd{exec.Command("./python", args...)}
}
diff --git a/test/runtimes/runner/BUILD b/test/runtimes/runner/BUILD
index 3972244b9..dc0d5d5b4 100644
--- a/test/runtimes/runner/BUILD
+++ b/test/runtimes/runner/BUILD
@@ -8,6 +8,7 @@ go_binary(
srcs = ["main.go"],
visibility = ["//test/runtimes:__pkg__"],
deps = [
+ "//pkg/log",
"//pkg/test/dockerutil",
"//pkg/test/testutil",
],
diff --git a/test/runtimes/runner/exclude_test.go b/test/runtimes/runner/exclude_test.go
index c08755894..67c2170c8 100644
--- a/test/runtimes/runner/exclude_test.go
+++ b/test/runtimes/runner/exclude_test.go
@@ -26,7 +26,7 @@ func TestMain(m *testing.M) {
}
// Test that the exclude file parses without error.
-func TestBlacklists(t *testing.T) {
+func TestExcludelist(t *testing.T) {
ex, err := getExcludes()
if err != nil {
t.Fatalf("error parsing exclude file: %v", err)
diff --git a/test/runtimes/runner/main.go b/test/runtimes/runner/main.go
index 2a0f62c73..e230912c9 100644
--- a/test/runtimes/runner/main.go
+++ b/test/runtimes/runner/main.go
@@ -27,6 +27,7 @@ import (
"testing"
"time"
+ "gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/test/dockerutil"
"gvisor.dev/gvisor/pkg/test/testutil"
)
@@ -35,10 +36,11 @@ var (
lang = flag.String("lang", "", "language runtime to test")
image = flag.String("image", "", "docker image with runtime tests")
excludeFile = flag.String("exclude_file", "", "file containing list of tests to exclude, in CSV format with fields: test name, bug id, comment")
+ batchSize = flag.Int("batch", 50, "number of test cases run in one command")
)
// Wait time for each test to run.
-const timeout = 5 * time.Minute
+const timeout = 45 * time.Minute
func main() {
flag.Parse()
@@ -110,17 +112,23 @@ func getTests(ctx context.Context, d *dockerutil.Container, excludes map[string]
}
var itests []testing.InternalTest
- for _, tci := range indices {
- // Capture tc in this scope.
- tc := tests[tci]
+ for i := 0; i < len(indices); i += *batchSize {
+ var tcs []string
+ end := i + *batchSize
+ if end > len(indices) {
+ end = len(indices)
+ }
+ for _, tc := range indices[i:end] {
+ // Add test if not excluded.
+ if _, ok := excludes[tests[tc]]; ok {
+ log.Infof("Skipping test case %s\n", tests[tc])
+ continue
+ }
+ tcs = append(tcs, tests[tc])
+ }
itests = append(itests, testing.InternalTest{
- Name: tc,
+ Name: strings.Join(tcs, ", "),
F: func(t *testing.T) {
- // Is the test excluded?
- if _, ok := excludes[tc]; ok {
- t.Skipf("SKIP: excluded test %q", tc)
- }
-
var (
now = time.Now()
done = make(chan struct{})
@@ -129,20 +137,20 @@ func getTests(ctx context.Context, d *dockerutil.Container, excludes map[string]
)
go func() {
- fmt.Printf("RUNNING %s...\n", tc)
- output, err = d.Exec(ctx, dockerutil.ExecOpts{}, "/proctor/proctor", "--runtime", *lang, "--test", tc)
+ fmt.Printf("RUNNING the following in a batch\n%s\n", strings.Join(tcs, "\n"))
+ output, err = d.Exec(ctx, dockerutil.ExecOpts{}, "/proctor/proctor", "--runtime", *lang, "--tests", strings.Join(tcs, ","))
close(done)
}()
select {
case <-done:
if err == nil {
- fmt.Printf("PASS: %s (%v)\n\n", tc, time.Since(now))
+ fmt.Printf("PASS: (%v)\n\n", time.Since(now))
return
}
- t.Errorf("FAIL: %s (%v):\n%s\n", tc, time.Since(now), output)
+ t.Errorf("FAIL: (%v):\n%s\n", time.Since(now), output)
case <-time.After(timeout):
- t.Errorf("TIMEOUT: %s (%v):\n%s\n", tc, time.Since(now), output)
+ t.Errorf("TIMEOUT: (%v):\n%s\n", time.Since(now), output)
}
},
})
diff --git a/test/syscalls/linux/BUILD b/test/syscalls/linux/BUILD
index 9e097c888..662d780d8 100644
--- a/test/syscalls/linux/BUILD
+++ b/test/syscalls/linux/BUILD
@@ -1330,6 +1330,7 @@ cc_binary(
name = "packet_socket_raw_test",
testonly = 1,
srcs = ["packet_socket_raw.cc"],
+ defines = select_system(),
linkstatic = 1,
deps = [
":socket_test_util",
@@ -1809,6 +1810,7 @@ cc_binary(
name = "raw_socket_test",
testonly = 1,
srcs = ["raw_socket.cc"],
+ defines = select_system(),
linkstatic = 1,
deps = [
":socket_test_util",
@@ -3407,6 +3409,7 @@ cc_binary(
name = "tcp_socket_test",
testonly = 1,
srcs = ["tcp_socket.cc"],
+ defines = select_system(),
linkstatic = 1,
deps = [
":socket_test_util",
diff --git a/test/syscalls/linux/packet_socket_raw.cc b/test/syscalls/linux/packet_socket_raw.cc
index 4093ac813..6a963b12c 100644
--- a/test/syscalls/linux/packet_socket_raw.cc
+++ b/test/syscalls/linux/packet_socket_raw.cc
@@ -14,6 +14,9 @@
#include <arpa/inet.h>
#include <linux/capability.h>
+#ifndef __fuchsia__
+#include <linux/filter.h>
+#endif // __fuchsia__
#include <linux/if_arp.h>
#include <linux/if_packet.h>
#include <net/ethernet.h>
@@ -556,6 +559,37 @@ TEST_P(RawPacketTest, SetSocketSendBuf) {
ASSERT_EQ(quarter_sz, val);
}
+#ifndef __fuchsia__
+
+TEST_P(RawPacketTest, SetSocketDetachFilterNoInstalledFilter) {
+ // TODO(gvisor.dev/2746): Support SO_ATTACH_FILTER/SO_DETACH_FILTER.
+ //
+ // gVisor returns no error on SO_DETACH_FILTER even if there is no filter
+ // attached unlike linux which does return ENOENT in such cases. This is
+ // because gVisor doesn't support SO_ATTACH_FILTER and just silently returns
+ // success.
+ if (IsRunningOnGvisor()) {
+ constexpr int val = 0;
+ ASSERT_THAT(setsockopt(s_, SOL_SOCKET, SO_DETACH_FILTER, &val, sizeof(val)),
+ SyscallSucceeds());
+ return;
+ }
+ constexpr int val = 0;
+ ASSERT_THAT(setsockopt(s_, SOL_SOCKET, SO_DETACH_FILTER, &val, sizeof(val)),
+ SyscallFailsWithErrno(ENOENT));
+}
+
+TEST_P(RawPacketTest, GetSocketDetachFilter) {
+ SKIP_IF(!ASSERT_NO_ERRNO_AND_VALUE(HaveCapability(CAP_NET_RAW)));
+
+ int val = 0;
+ socklen_t val_len = sizeof(val);
+ ASSERT_THAT(getsockopt(s_, SOL_SOCKET, SO_DETACH_FILTER, &val, &val_len),
+ SyscallFailsWithErrno(ENOPROTOOPT));
+}
+
+#endif // __fuchsia__
+
INSTANTIATE_TEST_SUITE_P(AllInetTests, RawPacketTest,
::testing::Values(ETH_P_IP, ETH_P_ALL));
diff --git a/test/syscalls/linux/raw_socket.cc b/test/syscalls/linux/raw_socket.cc
index 05c4ed03f..ce54dc064 100644
--- a/test/syscalls/linux/raw_socket.cc
+++ b/test/syscalls/linux/raw_socket.cc
@@ -13,6 +13,9 @@
// limitations under the License.
#include <linux/capability.h>
+#ifndef __fuchsia__
+#include <linux/filter.h>
+#endif // __fuchsia__
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip6.h>
@@ -21,6 +24,7 @@
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
+
#include <algorithm>
#include "gtest/gtest.h"
@@ -790,10 +794,30 @@ void RawSocketTest::ReceiveBufFrom(int sock, char* recv_buf,
ASSERT_NO_FATAL_FAILURE(RecvNoCmsg(sock, recv_buf, recv_buf_len));
}
-INSTANTIATE_TEST_SUITE_P(AllInetTests, RawSocketTest,
- ::testing::Combine(
- ::testing::Values(IPPROTO_TCP, IPPROTO_UDP),
- ::testing::Values(AF_INET, AF_INET6)));
+#ifndef __fuchsia__
+
+TEST_P(RawSocketTest, SetSocketDetachFilterNoInstalledFilter) {
+ // TODO(gvisor.dev/2746): Support SO_ATTACH_FILTER/SO_DETACH_FILTER.
+ if (IsRunningOnGvisor()) {
+ constexpr int val = 0;
+ ASSERT_THAT(setsockopt(s_, SOL_SOCKET, SO_DETACH_FILTER, &val, sizeof(val)),
+ SyscallSucceeds());
+ return;
+ }
+
+ constexpr int val = 0;
+ ASSERT_THAT(setsockopt(s_, SOL_SOCKET, SO_DETACH_FILTER, &val, sizeof(val)),
+ SyscallFailsWithErrno(ENOENT));
+}
+
+TEST_P(RawSocketTest, GetSocketDetachFilter) {
+ int val = 0;
+ socklen_t val_len = sizeof(val);
+ ASSERT_THAT(getsockopt(s_, SOL_SOCKET, SO_DETACH_FILTER, &val, &val_len),
+ SyscallFailsWithErrno(ENOPROTOOPT));
+}
+
+#endif // __fuchsia__
// AF_INET6+SOCK_RAW+IPPROTO_RAW sockets can be created, but not written to.
TEST(RawSocketTest, IPv6ProtoRaw) {
@@ -813,6 +837,11 @@ TEST(RawSocketTest, IPv6ProtoRaw) {
SyscallFailsWithErrno(EINVAL));
}
+INSTANTIATE_TEST_SUITE_P(
+ AllInetTests, RawSocketTest,
+ ::testing::Combine(::testing::Values(IPPROTO_TCP, IPPROTO_UDP),
+ ::testing::Values(AF_INET, AF_INET6)));
+
} // namespace
} // namespace testing
diff --git a/test/syscalls/linux/tcp_socket.cc b/test/syscalls/linux/tcp_socket.cc
index a4d2953e1..0cea7d11f 100644
--- a/test/syscalls/linux/tcp_socket.cc
+++ b/test/syscalls/linux/tcp_socket.cc
@@ -13,6 +13,9 @@
// limitations under the License.
#include <fcntl.h>
+#ifndef __fuchsia__
+#include <linux/filter.h>
+#endif // __fuchsia__
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <poll.h>
@@ -1559,6 +1562,63 @@ TEST_P(SimpleTcpSocketTest, SetTCPWindowClampAboveHalfMinRcvBuf) {
}
}
+#ifndef __fuchsia__
+
+// TODO(gvisor.dev/2746): Support SO_ATTACH_FILTER/SO_DETACH_FILTER.
+// gVisor currently silently ignores attaching a filter.
+TEST_P(SimpleTcpSocketTest, SetSocketAttachDetachFilter) {
+ FileDescriptor s =
+ ASSERT_NO_ERRNO_AND_VALUE(Socket(GetParam(), SOCK_STREAM, IPPROTO_TCP));
+ // Program generated using sudo tcpdump -i lo tcp and port 1234 -dd
+ struct sock_filter code[] = {
+ {0x28, 0, 0, 0x0000000c}, {0x15, 0, 6, 0x000086dd},
+ {0x30, 0, 0, 0x00000014}, {0x15, 0, 15, 0x00000006},
+ {0x28, 0, 0, 0x00000036}, {0x15, 12, 0, 0x000004d2},
+ {0x28, 0, 0, 0x00000038}, {0x15, 10, 11, 0x000004d2},
+ {0x15, 0, 10, 0x00000800}, {0x30, 0, 0, 0x00000017},
+ {0x15, 0, 8, 0x00000006}, {0x28, 0, 0, 0x00000014},
+ {0x45, 6, 0, 0x00001fff}, {0xb1, 0, 0, 0x0000000e},
+ {0x48, 0, 0, 0x0000000e}, {0x15, 2, 0, 0x000004d2},
+ {0x48, 0, 0, 0x00000010}, {0x15, 0, 1, 0x000004d2},
+ {0x6, 0, 0, 0x00040000}, {0x6, 0, 0, 0x00000000},
+ };
+ struct sock_fprog bpf = {
+ .len = ABSL_ARRAYSIZE(code),
+ .filter = code,
+ };
+ ASSERT_THAT(
+ setsockopt(s.get(), SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof(bpf)),
+ SyscallSucceeds());
+
+ constexpr int val = 0;
+ ASSERT_THAT(
+ setsockopt(s.get(), SOL_SOCKET, SO_DETACH_FILTER, &val, sizeof(val)),
+ SyscallSucceeds());
+}
+
+TEST_P(SimpleTcpSocketTest, SetSocketDetachFilterNoInstalledFilter) {
+ // TODO(gvisor.dev/2746): Support SO_ATTACH_FILTER/SO_DETACH_FILTER.
+ SKIP_IF(IsRunningOnGvisor());
+ FileDescriptor s =
+ ASSERT_NO_ERRNO_AND_VALUE(Socket(GetParam(), SOCK_STREAM, IPPROTO_TCP));
+ constexpr int val = 0;
+ ASSERT_THAT(
+ setsockopt(s.get(), SOL_SOCKET, SO_DETACH_FILTER, &val, sizeof(val)),
+ SyscallFailsWithErrno(ENOENT));
+}
+
+TEST_P(SimpleTcpSocketTest, GetSocketDetachFilter) {
+ FileDescriptor s =
+ ASSERT_NO_ERRNO_AND_VALUE(Socket(GetParam(), SOCK_STREAM, IPPROTO_TCP));
+
+ int val = 0;
+ socklen_t val_len = sizeof(val);
+ ASSERT_THAT(getsockopt(s.get(), SOL_SOCKET, SO_DETACH_FILTER, &val, &val_len),
+ SyscallFailsWithErrno(ENOPROTOOPT));
+}
+
+#endif // __fuchsia__
+
INSTANTIATE_TEST_SUITE_P(AllInetTests, SimpleTcpSocketTest,
::testing::Values(AF_INET, AF_INET6));
diff --git a/test/syscalls/linux/udp_socket_test_cases.cc b/test/syscalls/linux/udp_socket_test_cases.cc
index 9cc6be4fb..60c48ed6e 100644
--- a/test/syscalls/linux/udp_socket_test_cases.cc
+++ b/test/syscalls/linux/udp_socket_test_cases.cc
@@ -16,6 +16,9 @@
#include <arpa/inet.h>
#include <fcntl.h>
+#ifndef __fuchsia__
+#include <linux/filter.h>
+#endif // __fuchsia__
#include <netinet/in.h>
#include <poll.h>
#include <sys/ioctl.h>
@@ -1723,5 +1726,56 @@ TEST_P(UdpSocketTest, RecvBufLimits) {
}
}
+#ifndef __fuchsia__
+
+// TODO(gvisor.dev/2746): Support SO_ATTACH_FILTER/SO_DETACH_FILTER.
+// gVisor currently silently ignores attaching a filter.
+TEST_P(UdpSocketTest, SetSocketDetachFilter) {
+ // Program generated using sudo tcpdump -i lo udp and port 1234 -dd
+ struct sock_filter code[] = {
+ {0x28, 0, 0, 0x0000000c}, {0x15, 0, 6, 0x000086dd},
+ {0x30, 0, 0, 0x00000014}, {0x15, 0, 15, 0x00000011},
+ {0x28, 0, 0, 0x00000036}, {0x15, 12, 0, 0x000004d2},
+ {0x28, 0, 0, 0x00000038}, {0x15, 10, 11, 0x000004d2},
+ {0x15, 0, 10, 0x00000800}, {0x30, 0, 0, 0x00000017},
+ {0x15, 0, 8, 0x00000011}, {0x28, 0, 0, 0x00000014},
+ {0x45, 6, 0, 0x00001fff}, {0xb1, 0, 0, 0x0000000e},
+ {0x48, 0, 0, 0x0000000e}, {0x15, 2, 0, 0x000004d2},
+ {0x48, 0, 0, 0x00000010}, {0x15, 0, 1, 0x000004d2},
+ {0x6, 0, 0, 0x00040000}, {0x6, 0, 0, 0x00000000},
+ };
+ struct sock_fprog bpf = {
+ .len = ABSL_ARRAYSIZE(code),
+ .filter = code,
+ };
+ ASSERT_THAT(
+ setsockopt(sock_.get(), SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof(bpf)),
+ SyscallSucceeds());
+
+ constexpr int val = 0;
+ ASSERT_THAT(
+ setsockopt(sock_.get(), SOL_SOCKET, SO_DETACH_FILTER, &val, sizeof(val)),
+ SyscallSucceeds());
+}
+
+TEST_P(UdpSocketTest, SetSocketDetachFilterNoInstalledFilter) {
+ // TODO(gvisor.dev/2746): Support SO_ATTACH_FILTER/SO_DETACH_FILTER.
+ SKIP_IF(IsRunningOnGvisor());
+ constexpr int val = 0;
+ ASSERT_THAT(
+ setsockopt(sock_.get(), SOL_SOCKET, SO_DETACH_FILTER, &val, sizeof(val)),
+ SyscallFailsWithErrno(ENOENT));
+}
+
+TEST_P(UdpSocketTest, GetSocketDetachFilter) {
+ int val = 0;
+ socklen_t val_len = sizeof(val);
+ ASSERT_THAT(
+ getsockopt(sock_.get(), SOL_SOCKET, SO_DETACH_FILTER, &val, &val_len),
+ SyscallFailsWithErrno(ENOPROTOOPT));
+}
+
+#endif // __fuchsia__
+
} // namespace testing
} // namespace gvisor
diff --git a/test/util/test_util.h b/test/util/test_util.h
index 109078fc7..0f9781038 100644
--- a/test/util/test_util.h
+++ b/test/util/test_util.h
@@ -567,6 +567,25 @@ ssize_t ApplyFileIoSyscall(F const& f, size_t const count) {
} // namespace internal
+inline PosixErrorOr<std::string> ReadAllFd(int fd) {
+ std::string all;
+ all.reserve(128 * 1024); // arbitrary.
+
+ std::vector<char> buffer(16 * 1024);
+ for (;;) {
+ auto const bytes = RetryEINTR(read)(fd, buffer.data(), buffer.size());
+ if (bytes < 0) {
+ return PosixError(errno, "file read");
+ }
+ if (bytes == 0) {
+ return std::move(all);
+ }
+ if (bytes > 0) {
+ all.append(buffer.data(), bytes);
+ }
+ }
+}
+
inline ssize_t ReadFd(int fd, void* buf, size_t count) {
return internal::ApplyFileIoSyscall(
[&](size_t completed) {
diff --git a/tools/go.sh b/tools/go.sh
deleted file mode 100755
index b10ad18da..000000000
--- a/tools/go.sh
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/bin/bash
-
-# Copyright 2020 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 -eo pipefail
-
-# Build the :gopath target.
-make build TARGETS=":gopath"
-declare -r gopathdir="bazel-bin/gopath/src/gvisor.dev/gvisor/"
-
-# Copy go.mod and execute the command.
-cp -a go.mod go.sum "${gopathdir}"
-(cd "${gopathdir}" && go "$@")
-cp -a "${gopathdir}/go.mod" "${gopathdir}/go.sum" .
-
-# Cleanup the WORKSPACE file.
-make run TARGETS=":gazelle" ARGS="update-repos -from_file=go.mod"
diff --git a/tools/go_generics/defs.bzl b/tools/go_generics/defs.bzl
index 8c9995fd4..ec047a644 100644
--- a/tools/go_generics/defs.bzl
+++ b/tools/go_generics/defs.bzl
@@ -1,11 +1,24 @@
+"""Generics support via go_generics."""
+
+TemplateInfo = provider(
+ fields = {
+ "types": "required types",
+ "opt_types": "optional types",
+ "consts": "required consts",
+ "opt_consts": "optional consts",
+ "deps": "package dependencies",
+ "file": "merged template",
+ },
+)
+
def _go_template_impl(ctx):
- input = ctx.files.srcs
+ srcs = ctx.files.srcs
output = ctx.outputs.out
- args = ["-o=%s" % output.path] + [f.path for f in input]
+ args = ["-o=%s" % output.path] + [f.path for f in srcs]
ctx.actions.run(
- inputs = input,
+ inputs = srcs,
outputs = [output],
mnemonic = "GoGenericsTemplate",
progress_message = "Building Go template %s" % ctx.label,
@@ -13,14 +26,14 @@ def _go_template_impl(ctx):
executable = ctx.executable._tool,
)
- return struct(
+ return [TemplateInfo(
types = ctx.attr.types,
opt_types = ctx.attr.opt_types,
consts = ctx.attr.consts,
opt_consts = ctx.attr.opt_consts,
deps = ctx.attr.deps,
file = output,
- )
+ )]
"""
Generates a Go template from a set of Go files.
@@ -43,7 +56,7 @@ go_template = rule(
implementation = _go_template_impl,
attrs = {
"srcs": attr.label_list(mandatory = True, allow_files = True),
- "deps": attr.label_list(allow_files = True),
+ "deps": attr.label_list(allow_files = True, cfg = "target"),
"types": attr.string_list(),
"opt_types": attr.string_list(),
"consts": attr.string_list(),
@@ -55,8 +68,14 @@ go_template = rule(
},
)
+TemplateInstanceInfo = provider(
+ fields = {
+ "srcs": "source files",
+ },
+)
+
def _go_template_instance_impl(ctx):
- template = ctx.attr.template
+ template = ctx.attr.template[TemplateInfo]
output = ctx.outputs.out
# Check that all required types are defined.
@@ -105,9 +124,9 @@ def _go_template_instance_impl(ctx):
executable = ctx.executable._tool,
)
- return struct(
- files = depset([output]),
- )
+ return [TemplateInstanceInfo(
+ srcs = [output],
+ )]
"""
Instantiates a Go template by replacing all generic types with concrete ones.
@@ -125,7 +144,7 @@ Args:
go_template_instance = rule(
implementation = _go_template_instance_impl,
attrs = {
- "template": attr.label(mandatory = True, providers = ["types"]),
+ "template": attr.label(mandatory = True),
"prefix": attr.string(),
"suffix": attr.string(),
"types": attr.string_dict(),
diff --git a/tools/go_marshal/test/BUILD b/tools/go_marshal/test/BUILD
index 2fbcc8a03..3d989823a 100644
--- a/tools/go_marshal/test/BUILD
+++ b/tools/go_marshal/test/BUILD
@@ -39,6 +39,6 @@ go_test(
"//pkg/usermem",
"//tools/go_marshal/analysis",
"//tools/go_marshal/marshal",
- "@com_github_google_go-cmp//cmp:go_default_library",
+ "@com_github_google_go_cmp//cmp:go_default_library",
],
)
diff --git a/tools/installers/BUILD b/tools/installers/BUILD
index 017d8ca25..13d3cc5e0 100644
--- a/tools/installers/BUILD
+++ b/tools/installers/BUILD
@@ -5,19 +5,12 @@ package(
licenses = ["notice"],
)
-filegroup(
- name = "runsc",
- srcs = [
- "//runsc",
- "//shim/v1:gvisor-containerd-shim",
- "//shim/v2:containerd-shim-runsc-v1",
- ],
-)
-
sh_binary(
name = "head",
srcs = ["head.sh"],
- data = [":runsc"],
+ data = [
+ "//runsc",
+ ],
)
sh_binary(
@@ -37,3 +30,12 @@ sh_binary(
name = "containerd",
srcs = ["containerd.sh"],
)
+
+sh_binary(
+ name = "shim",
+ srcs = ["shim.sh"],
+ data = [
+ "//shim/v1:gvisor-containerd-shim",
+ "//shim/v2:containerd-shim-runsc-v1",
+ ],
+)
diff --git a/tools/installers/head.sh b/tools/installers/head.sh
index e6753f8a5..a613fcb5b 100755
--- a/tools/installers/head.sh
+++ b/tools/installers/head.sh
@@ -15,11 +15,11 @@
# limitations under the License.
# Install our runtime.
-$(find . -executable -type f -name runsc) install
-
-# Install all the shims.
-find . -executable -type f -executable -name containerd-shim-runsc-v1 -exec cp {} /usr/bin \;
-find . -executable -type f -executable -name gvisor-containerd-shim -exec cp {} /usr/bin \;
+runfiles=.
+if [[ -d "$0.runfiles" ]]; then
+ runfiles="$0.runfiles"
+fi
+$(find -L "${runfiles}" -executable -type f -name runsc) install
# Restart docker.
if service docker status 2>/dev/null; then
diff --git a/tools/installers/shim.sh b/tools/installers/shim.sh
index f7dd790a1..8153ce283 100755
--- a/tools/installers/shim.sh
+++ b/tools/installers/shim.sh
@@ -14,11 +14,20 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# 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}
-mv ${shim_path} /usr/local/bin/gvisor-containerd-shim
+# Install all the shims.
+#
+# Note that containerd looks at the current executable directory
+# in order to find the shim binary. So we need to check in order
+# of preference. The local containerd installer will install to
+# /usr/local, so we use that first.
+if [[ -x /usr/local/bin/containerd ]]; then
+ containerd_install_dir=/usr/local/bin
+else
+ containerd_install_dir=/usr/bin
+fi
+runfiles=.
+if [[ -d "$0.runfiles" ]]; then
+ runfiles="$0.runfiles"
+fi
+find -L "${runfiles}" -executable -type f -name containerd-shim-runsc-v1 -exec cp -L {} "${containerd_install_dir}" \;
+find -L "${runfiles}" -executable -type f -name gvisor-containerd-shim -exec cp -L {} "${containerd_install_dir}" \;
diff --git a/tools/issue_reviver/github/BUILD b/tools/issue_reviver/github/BUILD
index da4133472..8b1c717df 100644
--- a/tools/issue_reviver/github/BUILD
+++ b/tools/issue_reviver/github/BUILD
@@ -5,12 +5,13 @@ package(licenses = ["notice"])
go_library(
name = "github",
srcs = ["github.go"],
+ nogo = False,
visibility = [
"//tools/issue_reviver:__subpackages__",
],
deps = [
"//tools/issue_reviver/reviver",
- "@com_github_google_go-github//github:go_default_library",
+ "@com_github_google_go_github_v28//github:go_default_library",
"@org_golang_x_oauth2//:go_default_library",
],
)
diff --git a/tools/nogo/build.go b/tools/nogo/build.go
index 1c0d08661..fb9f17b62 100644
--- a/tools/nogo/build.go
+++ b/tools/nogo/build.go
@@ -32,5 +32,9 @@ var (
// findStdPkg needs to find the bundled standard library packages.
func findStdPkg(path, GOOS, GOARCH string) (io.ReadCloser, error) {
+ if path == "C" {
+ // Cgo builds cannot be analyzed. Skip.
+ return nil, ErrSkip
+ }
return os.Open(fmt.Sprintf("external/go_sdk/pkg/%s_%s/%s.a", GOOS, GOARCH, path))
}
diff --git a/tools/nogo/nogo.go b/tools/nogo/nogo.go
index 203cdf688..5ee586c3e 100644
--- a/tools/nogo/nogo.go
+++ b/tools/nogo/nogo.go
@@ -20,6 +20,7 @@ package nogo
import (
"encoding/json"
+ "errors"
"flag"
"fmt"
"go/ast"
@@ -89,8 +90,9 @@ func (c *pkgConfig) shouldInclude(path string) (bool, error) {
// pass when a given package is not available.
type importer struct {
pkgConfig
- fset *token.FileSet
- cache map[string]*types.Package
+ fset *token.FileSet
+ cache map[string]*types.Package
+ lastErr error
}
// Import implements types.Importer.Import.
@@ -115,6 +117,7 @@ func (i *importer) Import(path string) (*types.Package, error) {
rc, err = os.Open(realPath)
}
if err != nil {
+ i.lastErr = err
return nil, err
}
defer rc.Close()
@@ -128,6 +131,9 @@ func (i *importer) Import(path string) (*types.Package, error) {
return gcexportdata.Read(r, i.fset, i.cache, path)
}
+// ErrSkip indicates the package should be skipped.
+var ErrSkip = errors.New("skipped")
+
// checkPackage runs all analyzers.
//
// The implementation was adapted from [1], which was in turn adpated from [2].
@@ -172,14 +178,14 @@ func checkPackage(config pkgConfig) ([]string, error) {
Selections: make(map[*ast.SelectorExpr]*types.Selection),
}
types, err := typeConfig.Check(config.ImportPath, imp.fset, syntax, typesInfo)
- if err != nil {
- return nil, fmt.Errorf("error checking types: %v", err)
+ if err != nil && imp.lastErr != ErrSkip {
+ return nil, fmt.Errorf("error checking types: %w", err)
}
// Load all package facts.
facts, err := facts.Decode(types, config.loadFacts)
if err != nil {
- return nil, fmt.Errorf("error decoding facts: %v", err)
+ return nil, fmt.Errorf("error decoding facts: %w", err)
}
// Set the binary global for use.
@@ -247,6 +253,9 @@ func checkPackage(config pkgConfig) ([]string, error) {
// Visit all analysis recursively.
for a, _ := range analyzerConfig {
+ if imp.lastErr == ErrSkip {
+ continue // No local analysis.
+ }
if err := visit(a); err != nil {
return nil, err // Already has context.
}
diff --git a/tools/vm/ubuntu1604/30_docker.sh b/tools/vm/ubuntu1604/30_docker.sh
index 53d8ca588..36e55abd2 100755
--- a/tools/vm/ubuntu1604/30_docker.sh
+++ b/tools/vm/ubuntu1604/30_docker.sh
@@ -60,6 +60,3 @@ cat > /etc/docker/daemon.json <<EOF
"ipv6": true
}
EOF
-# Docker's IPv6 support is lacking and does not work the same way as IPv4. We
-# can use NAT so containers can reach the outside world.
-ip6tables -t nat -A POSTROUTING -s 2001:db8:1::/64 ! -o docker0 -j MASQUERADE
diff --git a/website/BUILD b/website/BUILD
index a1169739d..4488cb543 100644
--- a/website/BUILD
+++ b/website/BUILD
@@ -151,15 +151,12 @@ docs(
"//g3doc/user_guide:install",
"//g3doc/user_guide:networking",
"//g3doc/user_guide:platforms",
- "//g3doc/user_guide:runtimeclass",
"//g3doc/user_guide/quick_start:docker",
"//g3doc/user_guide/quick_start:kubernetes",
"//g3doc/user_guide/quick_start:oci",
"//g3doc/user_guide/tutorials:cni",
"//g3doc/user_guide/tutorials:docker",
"//g3doc/user_guide/tutorials:kubernetes",
- "//shim/v1:doc",
- "//shim/v2:doc",
],
)