mirror of https://github.com/k3s-io/k3s
[release 1.16] containerd: v1.3.10-k3s1 (#3083)
Addresses k3s-io/k3s#3077 and CVE-2021-21334 Signed-off-by: Jacob Blain Christen <jacob@rancher.com>release-1.16
parent
790b740f01
commit
31fddb21b5
|
@ -1,7 +1,7 @@
|
||||||
FROM golang:1.13.15-alpine3.12
|
FROM golang:1.13.15-alpine3.12
|
||||||
|
|
||||||
RUN apk -U --no-cache add bash git gcc musl-dev docker vim less file curl wget ca-certificates jq linux-headers zlib-dev tar zip squashfs-tools npm coreutils \
|
RUN apk -U --no-cache add bash git gcc musl-dev docker vim less file curl wget ca-certificates jq linux-headers zlib-dev tar zip squashfs-tools npm coreutils \
|
||||||
python2 openssl-dev libffi-dev libseccomp libseccomp-dev make libuv-static sqlite-dev sqlite-static libselinux libselinux-dev zlib-dev zlib-static
|
python2 openssl-dev libffi-dev libseccomp libseccomp-dev make libuv-dev libuv-static sqlite-dev sqlite-static libselinux libselinux-dev zlib-dev zlib-static
|
||||||
RUN mkdir -p /go/src/golang.org/x && \
|
RUN mkdir -p /go/src/golang.org/x && \
|
||||||
cd /go/src/golang.org/x && git clone https://github.com/golang/tools && \
|
cd /go/src/golang.org/x && git clone https://github.com/golang/tools && \
|
||||||
git -C /go/src/golang.org/x/tools checkout -b current aa82965741a9fecd12b026fbb3d3c6ed3231b8f8 && \
|
git -C /go/src/golang.org/x/tools checkout -b current aa82965741a9fecd12b026fbb3d3c6ed3231b8f8 && \
|
||||||
|
|
4
go.mod
4
go.mod
|
@ -8,9 +8,9 @@ replace (
|
||||||
github.com/containerd/btrfs => github.com/containerd/btrfs v0.0.0-20181101203652-af5082808c83
|
github.com/containerd/btrfs => github.com/containerd/btrfs v0.0.0-20181101203652-af5082808c83
|
||||||
github.com/containerd/cgroups => github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601
|
github.com/containerd/cgroups => github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601
|
||||||
github.com/containerd/console => github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50
|
github.com/containerd/console => github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50
|
||||||
github.com/containerd/containerd => github.com/rancher/containerd v1.3.0-k3s.5
|
github.com/containerd/containerd => github.com/rancher/containerd v1.3.10-k3s1
|
||||||
github.com/containerd/continuity => github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02
|
github.com/containerd/continuity => github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02
|
||||||
github.com/containerd/cri => github.com/rancher/cri v1.3.0-k3s.2
|
github.com/containerd/cri => github.com/rancher/cri v1.3.0-k3s.10
|
||||||
github.com/containerd/fifo => github.com/containerd/fifo v0.0.0-20190816180239-bda0ff6ed73c
|
github.com/containerd/fifo => github.com/containerd/fifo v0.0.0-20190816180239-bda0ff6ed73c
|
||||||
github.com/containerd/go-runc => github.com/containerd/go-runc v0.0.0-20190911050354-e029b79d8cda
|
github.com/containerd/go-runc => github.com/containerd/go-runc v0.0.0-20190911050354-e029b79d8cda
|
||||||
github.com/containerd/typeurl => github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd
|
github.com/containerd/typeurl => github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd
|
||||||
|
|
10
go.sum
10
go.sum
|
@ -389,7 +389,9 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.3.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
|
github.com/grpc-ecosystem/grpc-gateway v1.3.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.11.2 h1:bUDfHRK8aKGdya+msYJHffDwNxB8Eileyl7Jf2qqYjI=
|
github.com/grpc-ecosystem/grpc-gateway v1.11.2 h1:bUDfHRK8aKGdya+msYJHffDwNxB8Eileyl7Jf2qqYjI=
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.11.2/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
github.com/grpc-ecosystem/grpc-gateway v1.11.2/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||||
|
github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce h1:prjrVgOk2Yg6w+PflHoszQNLTUh4kaByUcEWM/9uin4=
|
||||||
github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||||
|
github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874 h1:cAv7ZbSmyb1wjn6T4TIiyFCkpcfgpbcNNC3bM2srLaI=
|
||||||
github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I=
|
github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I=
|
||||||
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
|
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
|
||||||
github.com/hashicorp/golang-lru v0.0.0-20180201235237-0fb14efe8c47/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
github.com/hashicorp/golang-lru v0.0.0-20180201235237-0fb14efe8c47/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
|
@ -585,10 +587,10 @@ github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:
|
||||||
github.com/quobyte/api v0.1.2/go.mod h1:jL7lIHrmqQ7yh05OJ+eEEdHr0u/kmT1Ff9iHd+4H6VI=
|
github.com/quobyte/api v0.1.2/go.mod h1:jL7lIHrmqQ7yh05OJ+eEEdHr0u/kmT1Ff9iHd+4H6VI=
|
||||||
github.com/rakelkar/gonetsh v0.0.0-20190719023240-501daadcadf8 h1:83l9gPhYtgxODlZKU0Odq4pQuDcMZEVgAh364+PV3OU=
|
github.com/rakelkar/gonetsh v0.0.0-20190719023240-501daadcadf8 h1:83l9gPhYtgxODlZKU0Odq4pQuDcMZEVgAh364+PV3OU=
|
||||||
github.com/rakelkar/gonetsh v0.0.0-20190719023240-501daadcadf8/go.mod h1:4XHkfaUj+URzGO9sohoAgt2V9Y8nIW7fugpu0E6gShk=
|
github.com/rakelkar/gonetsh v0.0.0-20190719023240-501daadcadf8/go.mod h1:4XHkfaUj+URzGO9sohoAgt2V9Y8nIW7fugpu0E6gShk=
|
||||||
github.com/rancher/containerd v1.3.0-k3s.5 h1:r5GheXz59KQpEdYPxRd53vfFhipnQG/g3MI5NkNPDQI=
|
github.com/rancher/containerd v1.3.10-k3s1 h1:PXYxupAyWAeNneHp6Xz77RIVV5sQQZkcBz1jNtv5HZE=
|
||||||
github.com/rancher/containerd v1.3.0-k3s.5/go.mod h1:ZMfzmqce2Z+QSEqdHMfeJs1TZ/UeJ1aDrazjpQT4ehM=
|
github.com/rancher/containerd v1.3.10-k3s1/go.mod h1:ZMfzmqce2Z+QSEqdHMfeJs1TZ/UeJ1aDrazjpQT4ehM=
|
||||||
github.com/rancher/cri v1.3.0-k3s.2 h1:k2XFyD+ZdsGvNfugdvqD38KSMANT3JmTFULFM2CtI70=
|
github.com/rancher/cri v1.3.0-k3s.10 h1:JPHitKhHThVM2qEgyZOjl2m88EDGeN90eEelqg0Sv7I=
|
||||||
github.com/rancher/cri v1.3.0-k3s.2/go.mod h1:Ht5T1dIKzm+4NExmb7wDVG6qR+j0xeXIjjhCv1d9geY=
|
github.com/rancher/cri v1.3.0-k3s.10/go.mod h1:Ht5T1dIKzm+4NExmb7wDVG6qR+j0xeXIjjhCv1d9geY=
|
||||||
github.com/rancher/cri-tools v1.16.1-k3s.1 h1:iporgQ46noE6dtLzq6fWcIO2qjyPZy2m42d2P+UnGJg=
|
github.com/rancher/cri-tools v1.16.1-k3s.1 h1:iporgQ46noE6dtLzq6fWcIO2qjyPZy2m42d2P+UnGJg=
|
||||||
github.com/rancher/cri-tools v1.16.1-k3s.1/go.mod h1:TEKhKv2EJIZp+p9jnEy4C63g8CosJzsI4kyKKkHag+8=
|
github.com/rancher/cri-tools v1.16.1-k3s.1/go.mod h1:TEKhKv2EJIZp+p9jnEy4C63g8CosJzsI4kyKKkHag+8=
|
||||||
github.com/rancher/dynamiclistener v0.2.0 h1:KucYwJXVVGhZ/NndfMCeQoCafT/VN7kvqSGgmlX8Lxk=
|
github.com/rancher/dynamiclistener v0.2.0 h1:KucYwJXVVGhZ/NndfMCeQoCafT/VN7kvqSGgmlX8Lxk=
|
||||||
|
|
|
@ -18,6 +18,6 @@ done
|
||||||
mkdir -p bin/aux && rm bin/mount && ln -sf ../busybox bin/aux/mount
|
mkdir -p bin/aux && rm bin/mount && ln -sf ../busybox bin/aux/mount
|
||||||
|
|
||||||
TRAEFIK_FILE=traefik-${TRAEFIK_VERSION}.tgz
|
TRAEFIK_FILE=traefik-${TRAEFIK_VERSION}.tgz
|
||||||
curl -sfL https://kubernetes-charts.storage.googleapis.com/${TRAEFIK_FILE} -o ${CHARTS_DIR}/${TRAEFIK_FILE}
|
curl -sfL https://charts.helm.sh/stable/packages/${TRAEFIK_FILE} -o ${CHARTS_DIR}/${TRAEFIK_FILE}
|
||||||
|
|
||||||
cp scripts/wg-add.sh bin/aux/
|
cp scripts/wg-add.sh bin/aux/
|
||||||
|
|
|
@ -7,12 +7,13 @@ clone_folder: c:\gopath\src\github.com\containerd\containerd
|
||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
|
- /release\/.*/
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
GOPATH: C:\gopath
|
GOPATH: C:\gopath
|
||||||
CGO_ENABLED: 1
|
CGO_ENABLED: 1
|
||||||
matrix:
|
matrix:
|
||||||
- GO_VERSION: 1.12.12
|
- GO_VERSION: 1.13.12
|
||||||
|
|
||||||
before_build:
|
before_build:
|
||||||
- choco install -y mingw --version 5.3.0
|
- choco install -y mingw --version 5.3.0
|
||||||
|
|
|
@ -15,7 +15,7 @@ linters:
|
||||||
- errcheck
|
- errcheck
|
||||||
|
|
||||||
run:
|
run:
|
||||||
deadline: 2m
|
deadline: 3m
|
||||||
skip-dirs:
|
skip-dirs:
|
||||||
- api
|
- api
|
||||||
- design
|
- design
|
||||||
|
|
|
@ -1,38 +1,77 @@
|
||||||
Abhinandan Prativadi <abhi@docker.com>
|
Abhinandan Prativadi <abhi@docker.com>
|
||||||
Abhinandan Prativadi <abhi@docker.com> <aprativadi@gmail.com>
|
Abhinandan Prativadi <abhi@docker.com> <aprativadi@gmail.com>
|
||||||
|
Ace-Tang <aceapril@126.com>
|
||||||
Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp> <suda.akihiro@lab.ntt.co.jp>
|
Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp> <suda.akihiro@lab.ntt.co.jp>
|
||||||
Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp> <suda.kyoto@gmail.com>
|
Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp> <suda.kyoto@gmail.com>
|
||||||
|
Allen Sun <shlallen1990@gmail.com> <allensun@AllenSundeMacBook-Pro.local>
|
||||||
|
Alexander Morozov <lk4d4math@gmail.com> <lk4d4@docker.com>
|
||||||
|
Amit Krishnan <krish.amit@gmail.com> <amit.krishnan@oracle.com>
|
||||||
Andrei Vagin <avagin@virtuozzo.com> <avagin@openvz.org>
|
Andrei Vagin <avagin@virtuozzo.com> <avagin@openvz.org>
|
||||||
Andrey Kolomentsev <andrey.kolomentsev@gmail.com>
|
Andrey Kolomentsev <andrey.kolomentsev@gmail.com>
|
||||||
|
Arnaud Porterie <icecrime@gmail.com>
|
||||||
|
Arnaud Porterie <icecrime@gmail.com> <arnaud.porterie@docker.com>
|
||||||
|
Bob Mader <swapdisk@users.noreply.github.com>
|
||||||
|
Boris Popovschi <zyqsempai@mail.ru>
|
||||||
|
Bowen Yan <loneybw@gmail.com>
|
||||||
Brent Baude <bbaude@redhat.com>
|
Brent Baude <bbaude@redhat.com>
|
||||||
|
Cao Zhihao <caozhihao@163.com>
|
||||||
|
Cao Zhihao <caozhihao@163.com> <caozhihao.xd@bytedance.com>
|
||||||
Carlos Eduardo <me@carlosedp.com> <me@carlosedp.com>
|
Carlos Eduardo <me@carlosedp.com> <me@carlosedp.com>
|
||||||
|
Cristian Staretu <cristian.staretu@gmail.com>
|
||||||
|
Cristian Staretu <cristian.staretu@gmail.com> <unclejack@users.noreply.github.com>
|
||||||
|
Daniel Dao <dqminh89@gmail.com>
|
||||||
|
Edgar Lee <edgarl@netflix.com> <edgar.lee@docker.com>
|
||||||
Eric Ren <renzhen.rz@alibaba-linux.com> <renzhen.rz@alibaba-inc.com>
|
Eric Ren <renzhen.rz@alibaba-linux.com> <renzhen.rz@alibaba-inc.com>
|
||||||
|
Fahed Dorgaa <fahed.dorgaa@gmail.com>
|
||||||
Frank Yang <yyb196@gmail.com>
|
Frank Yang <yyb196@gmail.com>
|
||||||
|
Fupan Li <lifupan@gmail.com>
|
||||||
Georgia Panoutsakopoulou <gpanoutsak@gmail.com>
|
Georgia Panoutsakopoulou <gpanoutsak@gmail.com>
|
||||||
Guangming Wang <guangming.wang@daocloud.io>
|
Guangming Wang <guangming.wang@daocloud.io>
|
||||||
Haiyan Meng <haiyanmeng@google.com>
|
Haiyan Meng <haiyanmeng@google.com>
|
||||||
|
Harry Zhang <harryz@hyper.sh> <harryzhang@zju.edu.cn>
|
||||||
|
Hu Shuai <hus.fnst@cn.fujitsu.com>
|
||||||
|
Hu Shuai <hus.fnst@cn.fujitsu.com> <hushuaiia@qq.com>
|
||||||
|
Jaana Burcu Dogan <burcujdogan@gmail.com> <jbd@golang.org>
|
||||||
|
Jess Valarezo <valarezo.jessica@gmail.com>
|
||||||
|
Jess Valarezo <valarezo.jessica@gmail.com> <jessica.valarezo@docker.com>
|
||||||
Jian Liao <jliao@alauda.io>
|
Jian Liao <jliao@alauda.io>
|
||||||
Jian Liao <jliao@alauda.io> <liaojian@Dabllo.local>
|
Jian Liao <jliao@alauda.io> <liaojian@Dabllo.local>
|
||||||
Ji'an Liu <anthonyliu@zju.edu.cn>
|
Ji'an Liu <anthonyliu@zju.edu.cn>
|
||||||
Jie Zhang <iamkadisi@163.com>
|
Jie Zhang <iamkadisi@163.com>
|
||||||
John Howard <john.howard@microsoft.com> <jhoward@microsoft.com>
|
John Howard <github@lowenna.com>
|
||||||
John Howard <john.howard@microsoft.com> <jhowardmsft@users.noreply.github.com>
|
John Howard <github@lowenna.com> <john.howard@microsoft.com>
|
||||||
|
John Howard <github@lowenna.com> <jhoward@microsoft.com>
|
||||||
|
John Howard <github@lowenna.com> <jhowardmsft@users.noreply.github.com>
|
||||||
|
Luc Perkins <lucperkins@gmail.com>
|
||||||
Julien Balestra <julien.balestra@datadoghq.com>
|
Julien Balestra <julien.balestra@datadoghq.com>
|
||||||
Justin Cormack <justin.cormack@docker.com> <justin@specialbusservice.com>
|
Justin Cormack <justin.cormack@docker.com> <justin@specialbusservice.com>
|
||||||
Justin Terry <juterry@microsoft.com>
|
Justin Terry <juterry@microsoft.com>
|
||||||
Justin Terry <juterry@microsoft.com> <jterry75@users.noreply.github.com>
|
Justin Terry <juterry@microsoft.com> <jterry75@users.noreply.github.com>
|
||||||
Kenfe-Mickaël Laventure <mickael.laventure@gmail.com>
|
Kenfe-Mickaël Laventure <mickael.laventure@gmail.com>
|
||||||
|
Kevin Kern <kaiwentan@harmonycloud.cn>
|
||||||
Kevin Xu <cming.xu@gmail.com>
|
Kevin Xu <cming.xu@gmail.com>
|
||||||
|
Kohei Tokunaga <ktokunaga.mail@gmail.com>
|
||||||
|
Krasi Georgiev <krasi.root@gmail.com> <krasi@vip-consult.solutions>
|
||||||
|
Lantao Liu <lantaol@google.com>
|
||||||
Lantao Liu <lantaol@google.com> <taotaotheripper@gmail.com>
|
Lantao Liu <lantaol@google.com> <taotaotheripper@gmail.com>
|
||||||
Lifubang <lifubang@aliyun.com> <lifubang@acmcoder.com>
|
Lifubang <lifubang@aliyun.com> <lifubang@acmcoder.com>
|
||||||
Lu Jingxiao <lujingxiao@huawei.com>
|
Lu Jingxiao <lujingxiao@huawei.com>
|
||||||
Maksym Pavlenko <makpav@amazon.com> <pavlenko.maksym@gmail.com>
|
Maksym Pavlenko <makpav@amazon.com> <pavlenko.maksym@gmail.com>
|
||||||
|
Mario Hros <spam@k3a.me>
|
||||||
|
Mario Hros <spam@k3a.me> <root@k3a.me>
|
||||||
Mark Gordon <msg555@gmail.com>
|
Mark Gordon <msg555@gmail.com>
|
||||||
Michael Katsoulis <michaelkatsoulis88@gmail.com>
|
Michael Katsoulis <michaelkatsoulis88@gmail.com>
|
||||||
Mike Brown <brownwm@us.ibm.com> <mikebrow@users.noreply.github.com>
|
Mike Brown <brownwm@us.ibm.com> <mikebrow@users.noreply.github.com>
|
||||||
Nishchay Kumar <mrawesomenix@gmail.com>
|
Nishchay Kumar <mrawesomenix@gmail.com>
|
||||||
|
Oliver Stenbom <oliver@stenbom.eu> <ostenbom@pivotal.io>
|
||||||
Phil Estes <estesp@gmail.com> <estesp@linux.vnet.ibm.com>
|
Phil Estes <estesp@gmail.com> <estesp@linux.vnet.ibm.com>
|
||||||
|
Reid Li <reid.li@utexas.edu>
|
||||||
|
Ross Boucher <rboucher@gmail.com>
|
||||||
|
Ruediger Maass <ruediger.maass@de.ibm.com>
|
||||||
Rui Cao <ruicao@alauda.io> <ruicao@alauda.io>
|
Rui Cao <ruicao@alauda.io> <ruicao@alauda.io>
|
||||||
|
Sakeven Jiang <jc5930@sina.cn>
|
||||||
|
Seth Pellegrino <spellegrino@newrelic.com> <30441101+sethp-nr@users.noreply.github.com>
|
||||||
|
Shengbo Song <thomassong@tencent.com>
|
||||||
Stephen J Day <stevvooe@gmail.com> <stephen.day@getcruise.com>
|
Stephen J Day <stevvooe@gmail.com> <stephen.day@getcruise.com>
|
||||||
Stephen J Day <stevvooe@gmail.com> <stevvooe@users.noreply.github.com>
|
Stephen J Day <stevvooe@gmail.com> <stevvooe@users.noreply.github.com>
|
||||||
Stephen J Day <stevvooe@gmail.com> <stephen.day@docker.com>
|
Stephen J Day <stevvooe@gmail.com> <stephen.day@docker.com>
|
||||||
|
@ -42,8 +81,12 @@ Tõnis Tiigi <tonistiigi@gmail.com>
|
||||||
Wei Fu <fuweid89@gmail.com> <fhfuwei@163.com>
|
Wei Fu <fuweid89@gmail.com> <fhfuwei@163.com>
|
||||||
Xiaodong Zhang <a4012017@sina.com>
|
Xiaodong Zhang <a4012017@sina.com>
|
||||||
Xuean Yan <yan.xuean@zte.com.cn>
|
Xuean Yan <yan.xuean@zte.com.cn>
|
||||||
|
Yue Zhang <zy675793960@yeah.net>
|
||||||
Yuxing Liu <starnop@163.com>
|
Yuxing Liu <starnop@163.com>
|
||||||
zhenguang zhu <zhengguang.zhu@daocloud.io>
|
Zhang Wei <zhangwei555@huawei.com>
|
||||||
zhongming chang<zhongming.chang@daocloud.io>
|
Zhenguang Zhu <zhengguang.zhu@daocloud.io>
|
||||||
zhoulin xie <zhoulin.xie@daocloud.io>
|
Zhiyu Li <payall4u@qq.com> <404977848@qq.com>
|
||||||
zhoulin xie <zhoulin.xie@daocloud.io> <42261994+JoeWrightss@users.noreply.github.com>
|
Zhongming Chang<zhongming.chang@daocloud.io>
|
||||||
|
Zhoulin Xie <zhoulin.xie@daocloud.io>
|
||||||
|
Zhoulin Xie <zhoulin.xie@daocloud.io> <42261994+JoeWrightss@users.noreply.github.com>
|
||||||
|
张潇 <xiaozhang0210@hotmail.com>
|
||||||
|
|
|
@ -4,19 +4,24 @@ sudo: required
|
||||||
services:
|
services:
|
||||||
- docker
|
- docker
|
||||||
|
|
||||||
|
branches:
|
||||||
|
except:
|
||||||
|
- master
|
||||||
|
- release/1.3
|
||||||
|
|
||||||
language: go
|
language: go
|
||||||
|
|
||||||
os:
|
os:
|
||||||
- linux
|
- linux
|
||||||
|
|
||||||
go:
|
go:
|
||||||
- "1.12.12"
|
- "1.13.15"
|
||||||
|
|
||||||
env:
|
env:
|
||||||
- TRAVIS_GOOS=linux TEST_RUNTIME=io.containerd.runc.v1 TRAVIS_CGO_ENABLED=1 TRAVIS_DISTRO=bionic
|
- TRAVIS_GOOS=linux TEST_RUNTIME=io.containerd.runc.v1 TRAVIS_CGO_ENABLED=1 TRAVIS_DISTRO=bionic GOPROXY=direct
|
||||||
- TRAVIS_GOOS=linux TEST_RUNTIME=io.containerd.runc.v2 TRAVIS_CGO_ENABLED=1 TRAVIS_DISTRO=bionic
|
- TRAVIS_GOOS=linux TEST_RUNTIME=io.containerd.runc.v2 TRAVIS_CGO_ENABLED=1 TRAVIS_DISTRO=bionic TRAVIS_RELEASE=yes GOPROXY=direct
|
||||||
- TRAVIS_GOOS=linux TEST_RUNTIME=io.containerd.runtime.v1.linux TRAVIS_CGO_ENABLED=1 TRAVIS_DISTRO=bionic
|
- TRAVIS_GOOS=linux TEST_RUNTIME=io.containerd.runtime.v1.linux TRAVIS_CGO_ENABLED=1 TRAVIS_DISTRO=bionic GOPROXY=direct
|
||||||
- TRAVIS_GOOS=darwin TRAVIS_CGO_ENABLED=0
|
- TRAVIS_GOOS=darwin TRAVIS_CGO_ENABLED=0 GOPROXY=direct
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
|
@ -24,7 +29,7 @@ matrix:
|
||||||
- if: type != pull_request
|
- if: type != pull_request
|
||||||
os: linux
|
os: linux
|
||||||
dist: xenial
|
dist: xenial
|
||||||
env: TRAVIS_GOOS=linux TEST_RUNTIME=io.containerd.runc.v2 TRAVIS_CGO_ENABLED=1 TRAVIS_DISTRO=xenial
|
env: TRAVIS_GOOS=linux TEST_RUNTIME=io.containerd.runc.v2 TRAVIS_CGO_ENABLED=1 TRAVIS_DISTRO=xenial GOPROXY=direct
|
||||||
|
|
||||||
go_import_path: github.com/containerd/containerd
|
go_import_path: github.com/containerd/containerd
|
||||||
|
|
||||||
|
@ -59,9 +64,9 @@ install:
|
||||||
- if [ "$TRAVIS_GOOS" = "linux" ]; then sudo PATH=$PATH GOPATH=$GOPATH script/setup/install-runc ; fi
|
- if [ "$TRAVIS_GOOS" = "linux" ]; then sudo PATH=$PATH GOPATH=$GOPATH script/setup/install-runc ; fi
|
||||||
- if [ "$TRAVIS_GOOS" = "linux" ]; then sudo PATH=$PATH GOPATH=$GOPATH script/setup/install-cni ; fi
|
- if [ "$TRAVIS_GOOS" = "linux" ]; then sudo PATH=$PATH GOPATH=$GOPATH script/setup/install-cni ; fi
|
||||||
- if [ "$TRAVIS_GOOS" = "linux" ]; then sudo PATH=$PATH GOPATH=$GOPATH script/setup/install-critools ; fi
|
- if [ "$TRAVIS_GOOS" = "linux" ]; then sudo PATH=$PATH GOPATH=$GOPATH script/setup/install-critools ; fi
|
||||||
- if [ "$TRAVIS_GOOS" = "linux" ]; then wget https://github.com/checkpoint-restore/criu/archive/v3.12.tar.gz -O /tmp/criu.tar.gz ; fi
|
- if [ "$TRAVIS_GOOS" = "linux" ]; then wget https://github.com/checkpoint-restore/criu/archive/v3.13.tar.gz -O /tmp/criu.tar.gz ; fi
|
||||||
- if [ "$TRAVIS_GOOS" = "linux" ]; then tar -C /tmp/ -zxf /tmp/criu.tar.gz ; fi
|
- if [ "$TRAVIS_GOOS" = "linux" ]; then tar -C /tmp/ -zxf /tmp/criu.tar.gz ; fi
|
||||||
- if [ "$TRAVIS_GOOS" = "linux" ]; then cd /tmp/criu-3.12 && sudo make install-criu ; fi
|
- if [ "$TRAVIS_GOOS" = "linux" ]; then cd /tmp/criu-3.13 && sudo make install-criu ; fi
|
||||||
- cd $TRAVIS_BUILD_DIR
|
- cd $TRAVIS_BUILD_DIR
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
|
@ -73,7 +78,7 @@ script:
|
||||||
- DCO_VERBOSITY=-q ../project/script/validate/dco
|
- DCO_VERBOSITY=-q ../project/script/validate/dco
|
||||||
- ../project/script/validate/fileheader ../project/
|
- ../project/script/validate/fileheader ../project/
|
||||||
- travis_wait ../project/script/validate/vendor
|
- travis_wait ../project/script/validate/vendor
|
||||||
- GOOS=linux script/setup/install-dev-tools
|
- GOOS=linux GO111MODULE=off script/setup/install-dev-tools
|
||||||
- go build -i .
|
- go build -i .
|
||||||
- make check
|
- make check
|
||||||
- if [ "$GOOS" = "linux" ]; then make check-protos check-api-descriptors; fi
|
- if [ "$GOOS" = "linux" ]; then make check-protos check-api-descriptors; fi
|
||||||
|
@ -83,9 +88,9 @@ script:
|
||||||
- if [ "$TRAVIS_GOOS" = "linux" ]; then sudo make install ; fi
|
- if [ "$TRAVIS_GOOS" = "linux" ]; then sudo make install ; fi
|
||||||
- if [ "$TRAVIS_GOOS" = "linux" ]; then make coverage ; fi
|
- if [ "$TRAVIS_GOOS" = "linux" ]; then make coverage ; fi
|
||||||
- if [ "$TRAVIS_GOOS" = "linux" ]; then sudo PATH=$PATH GOPATH=$GOPATH make root-coverage ; fi
|
- if [ "$TRAVIS_GOOS" = "linux" ]; then sudo PATH=$PATH GOPATH=$GOPATH make root-coverage ; fi
|
||||||
- if [ "$TRAVIS_GOOS" = "linux" ]; then sudo PATH=$PATH GOPATH=$GOPATH make integration ; fi
|
- if [ "$TRAVIS_GOOS" = "linux" ]; then sudo PATH=$PATH GOPATH=$GOPATH make integration EXTRA_TESTFLAGS=-no-criu ; fi
|
||||||
# Run the integration suite a second time. See discussion in github.com/containerd/containerd/pull/1759
|
# Run the integration suite a second time. See discussion in github.com/containerd/containerd/pull/1759
|
||||||
- if [ "$TRAVIS_GOOS" = "linux" ]; then sudo PATH=$PATH GOPATH=$GOPATH TESTFLAGS_PARALLEL=1 make integration ; fi
|
- if [ "$TRAVIS_GOOS" = "linux" ]; then sudo PATH=$PATH GOPATH=$GOPATH TESTFLAGS_PARALLEL=1 make integration EXTRA_TESTFLAGS=-no-criu ; fi
|
||||||
- |
|
- |
|
||||||
if [ "$TRAVIS_GOOS" = "linux" ]; then
|
if [ "$TRAVIS_GOOS" = "linux" ]; then
|
||||||
sudo mkdir -p /etc/containerd
|
sudo mkdir -p /etc/containerd
|
||||||
|
@ -107,8 +112,7 @@ after_success:
|
||||||
- bash <(curl -s https://codecov.io/bash) -F linux
|
- bash <(curl -s https://codecov.io/bash) -F linux
|
||||||
|
|
||||||
before_deploy:
|
before_deploy:
|
||||||
- make release
|
- if [ "$TRAVIS_RELEASE" = "yes" ]; then make release cri-release; fi
|
||||||
- if [ "$TRAVIS_GOOS" = "linux" ]; then make cri-release; fi
|
|
||||||
|
|
||||||
deploy:
|
deploy:
|
||||||
- provider: releases
|
- provider: releases
|
||||||
|
|
|
@ -207,7 +207,7 @@ Next, let's build `runc`:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cd /go/src/github.com/opencontainers/runc
|
cd /go/src/github.com/opencontainers/runc
|
||||||
make BUILDTAGS='seccomp apparmor' && make install
|
make BUILDTAGS='seccomp apparmor selinux' && make install
|
||||||
```
|
```
|
||||||
|
|
||||||
When working with `ctr`, the simple test client we just built, don't forget to start the daemon!
|
When working with `ctr`, the simple test client we just built, don't forget to start the daemon!
|
||||||
|
|
|
@ -80,9 +80,14 @@ TEST_REQUIRES_ROOT_PACKAGES=$(filter \
|
||||||
done | sort -u) \
|
done | sort -u) \
|
||||||
)
|
)
|
||||||
|
|
||||||
|
ifdef SKIPTESTS
|
||||||
|
PACKAGES:=$(filter-out ${SKIPTESTS},${PACKAGES})
|
||||||
|
TEST_REQUIRES_ROOT_PACKAGES:=$(filter-out ${SKIPTESTS},${TEST_REQUIRES_ROOT_PACKAGES})
|
||||||
|
endif
|
||||||
|
|
||||||
# Project binaries.
|
# Project binaries.
|
||||||
COMMANDS=ctr containerd containerd-stress
|
COMMANDS=ctr containerd containerd-stress
|
||||||
MANPAGES=ctr.1 containerd.1 containerd-config.1 containerd-config.toml.5
|
MANPAGES=ctr.8 containerd.8 containerd-config.8 containerd-config.toml.5
|
||||||
|
|
||||||
ifdef BUILDTAGS
|
ifdef BUILDTAGS
|
||||||
GO_BUILDTAGS = ${BUILDTAGS}
|
GO_BUILDTAGS = ${BUILDTAGS}
|
||||||
|
@ -111,7 +116,7 @@ GO_GCFLAGS=$(shell \
|
||||||
BINARIES=$(addprefix bin/,$(COMMANDS))
|
BINARIES=$(addprefix bin/,$(COMMANDS))
|
||||||
|
|
||||||
# Flags passed to `go test`
|
# Flags passed to `go test`
|
||||||
TESTFLAGS ?= $(TESTFLAGS_RACE)
|
TESTFLAGS ?= $(TESTFLAGS_RACE) $(EXTRA_TESTFLAGS)
|
||||||
TESTFLAGS_PARALLEL ?= 8
|
TESTFLAGS_PARALLEL ?= 8
|
||||||
|
|
||||||
.PHONY: clean all AUTHORS build binaries test integration generate protos checkprotos coverage ci check help install uninstall vendor release mandir install-man genman
|
.PHONY: clean all AUTHORS build binaries test integration generate protos checkprotos coverage ci check help install uninstall vendor release mandir install-man genman
|
||||||
|
@ -204,15 +209,15 @@ mandir:
|
||||||
@mkdir -p man
|
@mkdir -p man
|
||||||
|
|
||||||
# Kept for backwards compatability
|
# Kept for backwards compatability
|
||||||
genman: man/containerd.1 man/ctr.1
|
genman: man/containerd.8 man/ctr.8
|
||||||
|
|
||||||
man/containerd.1: FORCE
|
man/containerd.8: FORCE
|
||||||
@echo "$(WHALE) $@"
|
@echo "$(WHALE) $@"
|
||||||
go run cmd/gen-manpages/main.go containerd man/
|
go run cmd/gen-manpages/main.go $(@F) $(@D)
|
||||||
|
|
||||||
man/ctr.1: FORCE
|
man/ctr.8: FORCE
|
||||||
@echo "$(WHALE) $@"
|
@echo "$(WHALE) $@"
|
||||||
go run cmd/gen-manpages/main.go ctr man/
|
go run cmd/gen-manpages/main.go $(@F) $(@D)
|
||||||
|
|
||||||
man/%: docs/man/%.md FORCE
|
man/%: docs/man/%.md FORCE
|
||||||
@echo "$(WHALE) $@"
|
@echo "$(WHALE) $@"
|
||||||
|
|
|
@ -52,6 +52,6 @@ containerd is designed to be embedded into a larger system, hence it only includ
|
||||||
|
|
||||||
### How is the scope changed?
|
### How is the scope changed?
|
||||||
|
|
||||||
The scope of this project is a whitelist.
|
The scope of this project is an allowed list.
|
||||||
If it's not mentioned as being in scope, it is out of scope.
|
If it's not mentioned as being in scope, it is out of scope.
|
||||||
For the scope of this project to change it requires a 100% vote from all maintainers of the project.
|
For the scope of this project to change it requires a 100% vote from all maintainers of the project.
|
||||||
|
|
|
@ -71,7 +71,7 @@ var (
|
||||||
func init() {
|
func init() {
|
||||||
flag.BoolVar(&debugFlag, "debug", false, "enable debug output in logs")
|
flag.BoolVar(&debugFlag, "debug", false, "enable debug output in logs")
|
||||||
flag.StringVar(&namespaceFlag, "namespace", "", "namespace that owns the shim")
|
flag.StringVar(&namespaceFlag, "namespace", "", "namespace that owns the shim")
|
||||||
flag.StringVar(&socketFlag, "socket", "", "abstract socket path to serve")
|
flag.StringVar(&socketFlag, "socket", "", "socket path to serve")
|
||||||
flag.StringVar(&addressFlag, "address", "", "grpc address back to main containerd")
|
flag.StringVar(&addressFlag, "address", "", "grpc address back to main containerd")
|
||||||
flag.StringVar(&workdirFlag, "workdir", "", "path used to storge large temporary data")
|
flag.StringVar(&workdirFlag, "workdir", "", "path used to storge large temporary data")
|
||||||
flag.StringVar(&runtimeRootFlag, "runtime-root", process.RuncRoot, "root directory for the runtime")
|
flag.StringVar(&runtimeRootFlag, "runtime-root", process.RuncRoot, "root directory for the runtime")
|
||||||
|
@ -202,10 +202,18 @@ func serve(ctx context.Context, server *ttrpc.Server, path string) error {
|
||||||
f.Close()
|
f.Close()
|
||||||
path = "[inherited from parent]"
|
path = "[inherited from parent]"
|
||||||
} else {
|
} else {
|
||||||
if len(path) > 106 {
|
const (
|
||||||
return errors.Errorf("%q: unix socket path too long (> 106)", path)
|
abstractSocketPrefix = "\x00"
|
||||||
|
socketPathLimit = 106
|
||||||
|
)
|
||||||
|
p := strings.TrimPrefix(path, "unix://")
|
||||||
|
if len(p) == len(path) {
|
||||||
|
p = abstractSocketPrefix + p
|
||||||
}
|
}
|
||||||
l, err = net.Listen("unix", "\x00"+path)
|
if len(p) > socketPathLimit {
|
||||||
|
return errors.Errorf("%q: unix socket path too long (> %d)", p, socketPathLimit)
|
||||||
|
}
|
||||||
|
l, err = net.Listen("unix", p)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -227,6 +227,10 @@ can be used and modified as necessary as a custom configuration.`
|
||||||
}
|
}
|
||||||
serve(ctx, l, server.ServeGRPC)
|
serve(ctx, l, server.ServeGRPC)
|
||||||
|
|
||||||
|
if err := notifyReady(ctx); err != nil {
|
||||||
|
log.G(ctx).WithError(err).Warn("notify ready failed")
|
||||||
|
}
|
||||||
|
|
||||||
log.G(ctx).Infof("containerd successfully booted in %fs", time.Since(start).Seconds())
|
log.G(ctx).Infof("containerd successfully booted in %fs", time.Since(start).Seconds())
|
||||||
<-done
|
<-done
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -52,6 +52,10 @@ func handleSignals(ctx context.Context, signals chan os.Signal, serverC chan *se
|
||||||
case unix.SIGPIPE:
|
case unix.SIGPIPE:
|
||||||
continue
|
continue
|
||||||
default:
|
default:
|
||||||
|
if err := notifyStopping(ctx); err != nil {
|
||||||
|
log.G(ctx).WithError(err).Error("notify stopping failed")
|
||||||
|
}
|
||||||
|
|
||||||
if server == nil {
|
if server == nil {
|
||||||
close(done)
|
close(done)
|
||||||
return
|
return
|
||||||
|
|
|
@ -51,6 +51,11 @@ func handleSignals(ctx context.Context, signals chan os.Signal, serverC chan *se
|
||||||
server = s
|
server = s
|
||||||
case s := <-signals:
|
case s := <-signals:
|
||||||
log.G(ctx).WithField("signal", s).Debug("received signal")
|
log.G(ctx).WithField("signal", s).Debug("received signal")
|
||||||
|
|
||||||
|
if err := notifyStopping(ctx); err != nil {
|
||||||
|
log.G(ctx).WithError(err).Error("notify stopping failed")
|
||||||
|
}
|
||||||
|
|
||||||
if server == nil {
|
if server == nil {
|
||||||
close(done)
|
close(done)
|
||||||
return
|
return
|
||||||
|
|
62
vendor/github.com/containerd/containerd/cmd/containerd/command/notify_linux.go
generated
vendored
Normal file
62
vendor/github.com/containerd/containerd/cmd/containerd/command/notify_linux.go
generated
vendored
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
sd "github.com/coreos/go-systemd/daemon"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// SdNotifyReady tells the service manager that service startup is finished
|
||||||
|
// or the service finished loading its configuration.
|
||||||
|
SdNotifyReady = "READY=1"
|
||||||
|
|
||||||
|
// SdNotifyStopping tells the service manager that the service is beginning
|
||||||
|
// its shutdown.
|
||||||
|
SdNotifyStopping = "STOPPING=1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// notifyReady notifies systemd that the daemon is ready to serve requests
|
||||||
|
func notifyReady(ctx context.Context) error {
|
||||||
|
return sdNotify(ctx, SdNotifyReady)
|
||||||
|
}
|
||||||
|
|
||||||
|
// notifyStopping notifies systemd that the daemon is about to be stopped
|
||||||
|
func notifyStopping(ctx context.Context) error {
|
||||||
|
return sdNotify(ctx, SdNotifyStopping)
|
||||||
|
}
|
||||||
|
|
||||||
|
func sdNotify(ctx context.Context, state string) error {
|
||||||
|
if os.Getenv("NOTIFY_SOCKET") != "" {
|
||||||
|
notified, err := sd.SdNotify(false, state)
|
||||||
|
log.G(ctx).
|
||||||
|
WithError(err).
|
||||||
|
WithField("notified", notified).
|
||||||
|
WithField("state", state).
|
||||||
|
Debug("sd notification")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
31
vendor/github.com/containerd/containerd/cmd/containerd/command/notify_unsupported.go
generated
vendored
Normal file
31
vendor/github.com/containerd/containerd/cmd/containerd/command/notify_unsupported.go
generated
vendored
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// +build !linux
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
)
|
||||||
|
|
||||||
|
func notifyReady(ctx context.Context) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func notifyStopping(ctx context.Context) error {
|
||||||
|
return nil
|
||||||
|
}
|
35
vendor/github.com/containerd/containerd/cmd/containerd/command/service_windows.go
generated
vendored
35
vendor/github.com/containerd/containerd/cmd/containerd/command/service_windows.go
generated
vendored
|
@ -42,16 +42,17 @@ var (
|
||||||
registerServiceFlag bool
|
registerServiceFlag bool
|
||||||
unregisterServiceFlag bool
|
unregisterServiceFlag bool
|
||||||
runServiceFlag bool
|
runServiceFlag bool
|
||||||
|
logFileFlag string
|
||||||
|
|
||||||
kernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
kernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
||||||
setStdHandle = kernel32.NewProc("SetStdHandle")
|
setStdHandle = kernel32.NewProc("SetStdHandle")
|
||||||
allocConsole = kernel32.NewProc("AllocConsole")
|
allocConsole = kernel32.NewProc("AllocConsole")
|
||||||
oldStderr windows.Handle
|
oldStderr windows.Handle
|
||||||
panicFile *os.File
|
panicFile *os.File
|
||||||
|
|
||||||
service *handler
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const defaultServiceName = "containerd"
|
||||||
|
|
||||||
// serviceFlags returns an array of flags for configuring containerd to run
|
// serviceFlags returns an array of flags for configuring containerd to run
|
||||||
// as a Windows service under control of SCM.
|
// as a Windows service under control of SCM.
|
||||||
func serviceFlags() []cli.Flag {
|
func serviceFlags() []cli.Flag {
|
||||||
|
@ -59,7 +60,7 @@ func serviceFlags() []cli.Flag {
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "service-name",
|
Name: "service-name",
|
||||||
Usage: "Set the Windows service name",
|
Usage: "Set the Windows service name",
|
||||||
Value: "containerd",
|
Value: defaultServiceName,
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
cli.BoolFlag{
|
||||||
Name: "register-service",
|
Name: "register-service",
|
||||||
|
@ -74,14 +75,18 @@ func serviceFlags() []cli.Flag {
|
||||||
Usage: "",
|
Usage: "",
|
||||||
Hidden: true,
|
Hidden: true,
|
||||||
},
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "log-file",
|
||||||
|
Usage: "Path to the containerd log file",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// applyPlatformFlags applies platform-specific flags.
|
// applyPlatformFlags applies platform-specific flags.
|
||||||
func applyPlatformFlags(context *cli.Context) {
|
func applyPlatformFlags(context *cli.Context) {
|
||||||
|
serviceNameFlag = context.GlobalString("service-name")
|
||||||
if s := context.GlobalString("service-name"); s != "" {
|
if serviceNameFlag == "" {
|
||||||
serviceNameFlag = s
|
serviceNameFlag = defaultServiceName
|
||||||
}
|
}
|
||||||
for _, v := range []struct {
|
for _, v := range []struct {
|
||||||
name string
|
name string
|
||||||
|
@ -102,6 +107,7 @@ func applyPlatformFlags(context *cli.Context) {
|
||||||
} {
|
} {
|
||||||
*v.d = context.GlobalBool(v.name)
|
*v.d = context.GlobalBool(v.name)
|
||||||
}
|
}
|
||||||
|
logFileFlag = context.GlobalString("log-file")
|
||||||
}
|
}
|
||||||
|
|
||||||
type handler struct {
|
type handler struct {
|
||||||
|
@ -243,7 +249,15 @@ func registerUnregisterService(root string) (bool, error) {
|
||||||
return true, err
|
return true, err
|
||||||
}
|
}
|
||||||
|
|
||||||
logrus.SetOutput(ioutil.Discard)
|
logOutput := ioutil.Discard
|
||||||
|
if logFileFlag != "" {
|
||||||
|
f, err := os.OpenFile(logFileFlag, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return true, errors.Wrapf(err, "open log file %q", logFileFlag)
|
||||||
|
}
|
||||||
|
logOutput = f
|
||||||
|
}
|
||||||
|
logrus.SetOutput(logOutput)
|
||||||
}
|
}
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
@ -266,7 +280,6 @@ func launchService(s *server.Server, done chan struct{}) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
service = h
|
|
||||||
go func() {
|
go func() {
|
||||||
if interactive {
|
if interactive {
|
||||||
err = debug.Run(serviceNameFlag, h)
|
err = debug.Run(serviceNameFlag, h)
|
||||||
|
@ -334,8 +347,8 @@ func initPanicFile(path string) error {
|
||||||
// Update STD_ERROR_HANDLE to point to the panic file so that Go writes to
|
// Update STD_ERROR_HANDLE to point to the panic file so that Go writes to
|
||||||
// it when it panics. Remember the old stderr to restore it before removing
|
// it when it panics. Remember the old stderr to restore it before removing
|
||||||
// the panic file.
|
// the panic file.
|
||||||
sh := windows.STD_ERROR_HANDLE
|
sh := uint32(windows.STD_ERROR_HANDLE)
|
||||||
h, err := windows.GetStdHandle(uint32(sh))
|
h, err := windows.GetStdHandle(sh)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -359,7 +372,7 @@ func initPanicFile(path string) error {
|
||||||
func removePanicFile() {
|
func removePanicFile() {
|
||||||
if st, err := panicFile.Stat(); err == nil {
|
if st, err := panicFile.Stat(); err == nil {
|
||||||
if st.Size() == 0 {
|
if st.Size() == 0 {
|
||||||
sh := windows.STD_ERROR_HANDLE
|
sh := uint32(windows.STD_ERROR_HANDLE)
|
||||||
setStdHandle.Call(uintptr(sh), uintptr(oldStderr))
|
setStdHandle.Call(uintptr(sh), uintptr(oldStderr))
|
||||||
panicFile.Close()
|
panicFile.Close()
|
||||||
os.Remove(panicFile.Name())
|
os.Remove(panicFile.Name())
|
||||||
|
|
|
@ -24,6 +24,7 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/containerd/console"
|
"github.com/containerd/console"
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
"github.com/containerd/containerd/cmd/ctr/commands"
|
||||||
|
@ -240,10 +241,11 @@ func getTaskService(context *cli.Context) (task.TaskService, error) {
|
||||||
s1 := filepath.Join(string(filepath.Separator), "containerd-shim", ns, id, "shim.sock")
|
s1 := filepath.Join(string(filepath.Separator), "containerd-shim", ns, id, "shim.sock")
|
||||||
// this should not error, ctr always get a default ns
|
// this should not error, ctr always get a default ns
|
||||||
ctx := namespaces.WithNamespace(gocontext.Background(), ns)
|
ctx := namespaces.WithNamespace(gocontext.Background(), ns)
|
||||||
s2, _ := shim.SocketAddress(ctx, id)
|
s2, _ := shim.SocketAddress(ctx, context.GlobalString("address"), id)
|
||||||
|
s2 = strings.TrimPrefix(s2, "unix://")
|
||||||
|
|
||||||
for _, socket := range []string{s1, s2} {
|
for _, socket := range []string{s2, "\x00" + s1} {
|
||||||
conn, err := net.Dial("unix", "\x00"+socket)
|
conn, err := net.Dial("unix", socket)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
client := ttrpc.NewClient(conn)
|
client := ttrpc.NewClient(conn)
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -36,8 +37,16 @@ func ForwardAllSignals(ctx gocontext.Context, task killer) chan os.Signal {
|
||||||
signal.Notify(sigc)
|
signal.Notify(sigc)
|
||||||
go func() {
|
go func() {
|
||||||
for s := range sigc {
|
for s := range sigc {
|
||||||
|
if canIgnoreSignal(s) {
|
||||||
|
logrus.Debugf("Ignoring signal %s", s)
|
||||||
|
continue
|
||||||
|
}
|
||||||
logrus.Debug("forwarding signal ", s)
|
logrus.Debug("forwarding signal ", s)
|
||||||
if err := task.Kill(ctx, s.(syscall.Signal)); err != nil {
|
if err := task.Kill(ctx, s.(syscall.Signal)); err != nil {
|
||||||
|
if errdefs.IsNotFound(err) {
|
||||||
|
logrus.WithError(err).Debugf("Not forwarding signal %s", s)
|
||||||
|
return
|
||||||
|
}
|
||||||
logrus.WithError(err).Errorf("forward signal %s", s)
|
logrus.WithError(err).Errorf("forward signal %s", s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
27
vendor/github.com/containerd/containerd/cmd/ctr/commands/signals_linux.go
generated
vendored
Normal file
27
vendor/github.com/containerd/containerd/cmd/ctr/commands/signals_linux.go
generated
vendored
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
func canIgnoreSignal(s os.Signal) bool {
|
||||||
|
return s == unix.SIGURG
|
||||||
|
}
|
25
vendor/github.com/containerd/containerd/cmd/ctr/commands/signals_notlinux.go
generated
vendored
Normal file
25
vendor/github.com/containerd/containerd/cmd/ctr/commands/signals_notlinux.go
generated
vendored
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
//+build !linux
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package commands
|
||||||
|
|
||||||
|
import "os"
|
||||||
|
|
||||||
|
func canIgnoreSignal(_ os.Signal) bool {
|
||||||
|
return false
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
comment: false
|
|
@ -32,10 +32,12 @@ import (
|
||||||
"github.com/containerd/containerd/images"
|
"github.com/containerd/containerd/images"
|
||||||
"github.com/containerd/containerd/oci"
|
"github.com/containerd/containerd/oci"
|
||||||
"github.com/containerd/containerd/runtime/v2/runc/options"
|
"github.com/containerd/containerd/runtime/v2/runc/options"
|
||||||
|
"github.com/containerd/containerd/sys"
|
||||||
"github.com/containerd/typeurl"
|
"github.com/containerd/typeurl"
|
||||||
prototypes "github.com/gogo/protobuf/types"
|
prototypes "github.com/gogo/protobuf/types"
|
||||||
ver "github.com/opencontainers/image-spec/specs-go"
|
ver "github.com/opencontainers/image-spec/specs-go"
|
||||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
|
"github.com/opencontainers/selinux/go-selinux/label"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -242,7 +244,17 @@ func (c *container) NewTask(ctx context.Context, ioCreate cio.Creator, opts ...N
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
spec, err := c.Spec(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
for _, m := range mounts {
|
for _, m := range mounts {
|
||||||
|
if spec.Linux != nil && spec.Linux.MountLabel != "" {
|
||||||
|
context := label.FormatMountLabel("", spec.Linux.MountLabel)
|
||||||
|
if context != "" {
|
||||||
|
m.Options = append(m.Options, context)
|
||||||
|
}
|
||||||
|
}
|
||||||
request.Rootfs = append(request.Rootfs, &types.Mount{
|
request.Rootfs = append(request.Rootfs, &types.Mount{
|
||||||
Type: m.Type,
|
Type: m.Type,
|
||||||
Source: m.Source,
|
Source: m.Source,
|
||||||
|
@ -411,14 +423,33 @@ func attachExistingIO(response *tasks.GetResponse, ioAttach cio.Attach) (cio.IO,
|
||||||
|
|
||||||
// loadFifos loads the containers fifos
|
// loadFifos loads the containers fifos
|
||||||
func loadFifos(response *tasks.GetResponse) *cio.FIFOSet {
|
func loadFifos(response *tasks.GetResponse) *cio.FIFOSet {
|
||||||
path := getFifoDir([]string{
|
fifos := []string{
|
||||||
response.Process.Stdin,
|
response.Process.Stdin,
|
||||||
response.Process.Stdout,
|
response.Process.Stdout,
|
||||||
response.Process.Stderr,
|
response.Process.Stderr,
|
||||||
})
|
|
||||||
closer := func() error {
|
|
||||||
return os.RemoveAll(path)
|
|
||||||
}
|
}
|
||||||
|
closer := func() error {
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
dirs = map[string]struct{}{}
|
||||||
|
)
|
||||||
|
for _, fifo := range fifos {
|
||||||
|
if isFifo, _ := sys.IsFifo(fifo); isFifo {
|
||||||
|
if rerr := os.Remove(fifo); err == nil {
|
||||||
|
err = rerr
|
||||||
|
}
|
||||||
|
dirs[filepath.Dir(fifo)] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for dir := range dirs {
|
||||||
|
// we ignore errors here because we don't
|
||||||
|
// want to remove the directory if it isn't
|
||||||
|
// empty
|
||||||
|
os.Remove(dir)
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return cio.NewFIFOSet(cio.Config{
|
return cio.NewFIFOSet(cio.Config{
|
||||||
Stdin: response.Process.Stdin,
|
Stdin: response.Process.Stdin,
|
||||||
Stdout: response.Process.Stdout,
|
Stdout: response.Process.Stdout,
|
||||||
|
@ -426,14 +457,3 @@ func loadFifos(response *tasks.GetResponse) *cio.FIFOSet {
|
||||||
Terminal: response.Process.Terminal,
|
Terminal: response.Process.Terminal,
|
||||||
}, closer)
|
}, closer)
|
||||||
}
|
}
|
||||||
|
|
||||||
// getFifoDir looks for any non-empty path for a stdio fifo
|
|
||||||
// and returns the dir for where it is located
|
|
||||||
func getFifoDir(paths []string) string {
|
|
||||||
for _, p := range paths {
|
|
||||||
if p != "" {
|
|
||||||
return filepath.Dir(p)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
|
@ -87,21 +87,21 @@ func WithRestoreRuntime(ctx context.Context, id string, client *Client, checkpoi
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var options *ptypes.Any
|
var options ptypes.Any
|
||||||
if m != nil {
|
if m != nil {
|
||||||
store := client.ContentStore()
|
store := client.ContentStore()
|
||||||
data, err := content.ReadBlob(ctx, store, *m)
|
data, err := content.ReadBlob(ctx, store, *m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "unable to read checkpoint runtime")
|
return errors.Wrap(err, "unable to read checkpoint runtime")
|
||||||
}
|
}
|
||||||
if err := proto.Unmarshal(data, options); err != nil {
|
if err := proto.Unmarshal(data, &options); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Runtime = containers.RuntimeInfo{
|
c.Runtime = containers.RuntimeInfo{
|
||||||
Name: name,
|
Name: name,
|
||||||
Options: options,
|
Options: &options,
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,11 @@ After=network.target local-fs.target
|
||||||
ExecStartPre=-/sbin/modprobe overlay
|
ExecStartPre=-/sbin/modprobe overlay
|
||||||
ExecStart=/usr/local/bin/containerd
|
ExecStart=/usr/local/bin/containerd
|
||||||
|
|
||||||
|
Type=notify
|
||||||
Delegate=yes
|
Delegate=yes
|
||||||
KillMode=process
|
KillMode=process
|
||||||
Restart=always
|
Restart=always
|
||||||
|
RestartSec=5
|
||||||
# Having non-zero Limit*s causes performance problems due to accounting overhead
|
# Having non-zero Limit*s causes performance problems due to accounting overhead
|
||||||
# in the kernel. We recommend using cgroups to do container-local accounting.
|
# in the kernel. We recommend using cgroups to do container-local accounting.
|
||||||
LimitNPROC=infinity
|
LimitNPROC=infinity
|
||||||
|
@ -18,6 +20,7 @@ LimitNOFILE=1048576
|
||||||
# Comment TasksMax if your systemd version does not supports it.
|
# Comment TasksMax if your systemd version does not supports it.
|
||||||
# Only systemd 226 and above support this version.
|
# Only systemd 226 and above support this version.
|
||||||
TasksMax=infinity
|
TasksMax=infinity
|
||||||
|
OOMScoreAdjust=-999
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
|
|
|
@ -47,7 +47,7 @@ func arches() []specs.Arch {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultProfile defines the whitelist for the default seccomp profile.
|
// DefaultProfile defines the allowed syscalls for the default seccomp profile.
|
||||||
func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
|
func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
|
||||||
syscalls := []specs.LinuxSyscall{
|
syscalls := []specs.LinuxSyscall{
|
||||||
{
|
{
|
||||||
|
@ -55,7 +55,7 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
|
||||||
"accept",
|
"accept",
|
||||||
"accept4",
|
"accept4",
|
||||||
"access",
|
"access",
|
||||||
"alarm",
|
"adjtimex",
|
||||||
"alarm",
|
"alarm",
|
||||||
"bind",
|
"bind",
|
||||||
"brk",
|
"brk",
|
||||||
|
@ -65,9 +65,14 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
|
||||||
"chmod",
|
"chmod",
|
||||||
"chown",
|
"chown",
|
||||||
"chown32",
|
"chown32",
|
||||||
|
"clock_adjtime",
|
||||||
|
"clock_adjtime64",
|
||||||
"clock_getres",
|
"clock_getres",
|
||||||
|
"clock_getres_time64",
|
||||||
"clock_gettime",
|
"clock_gettime",
|
||||||
|
"clock_gettime64",
|
||||||
"clock_nanosleep",
|
"clock_nanosleep",
|
||||||
|
"clock_nanosleep_time64",
|
||||||
"close",
|
"close",
|
||||||
"connect",
|
"connect",
|
||||||
"copy_file_range",
|
"copy_file_range",
|
||||||
|
@ -89,6 +94,7 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
|
||||||
"exit",
|
"exit",
|
||||||
"exit_group",
|
"exit_group",
|
||||||
"faccessat",
|
"faccessat",
|
||||||
|
"faccessat2",
|
||||||
"fadvise64",
|
"fadvise64",
|
||||||
"fadvise64_64",
|
"fadvise64_64",
|
||||||
"fallocate",
|
"fallocate",
|
||||||
|
@ -117,6 +123,7 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
|
||||||
"ftruncate",
|
"ftruncate",
|
||||||
"ftruncate64",
|
"ftruncate64",
|
||||||
"futex",
|
"futex",
|
||||||
|
"futex_time64",
|
||||||
"futimesat",
|
"futimesat",
|
||||||
"getcpu",
|
"getcpu",
|
||||||
"getcwd",
|
"getcwd",
|
||||||
|
@ -163,10 +170,14 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
|
||||||
"io_destroy",
|
"io_destroy",
|
||||||
"io_getevents",
|
"io_getevents",
|
||||||
"io_pgetevents",
|
"io_pgetevents",
|
||||||
|
"io_pgetevents_time64",
|
||||||
"ioprio_get",
|
"ioprio_get",
|
||||||
"ioprio_set",
|
"ioprio_set",
|
||||||
"io_setup",
|
"io_setup",
|
||||||
"io_submit",
|
"io_submit",
|
||||||
|
"io_uring_enter",
|
||||||
|
"io_uring_register",
|
||||||
|
"io_uring_setup",
|
||||||
"ipc",
|
"ipc",
|
||||||
"kill",
|
"kill",
|
||||||
"lchown",
|
"lchown",
|
||||||
|
@ -184,6 +195,7 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
|
||||||
"lstat",
|
"lstat",
|
||||||
"lstat64",
|
"lstat64",
|
||||||
"madvise",
|
"madvise",
|
||||||
|
"membarrier",
|
||||||
"memfd_create",
|
"memfd_create",
|
||||||
"mincore",
|
"mincore",
|
||||||
"mkdir",
|
"mkdir",
|
||||||
|
@ -200,7 +212,9 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
|
||||||
"mq_notify",
|
"mq_notify",
|
||||||
"mq_open",
|
"mq_open",
|
||||||
"mq_timedreceive",
|
"mq_timedreceive",
|
||||||
|
"mq_timedreceive_time64",
|
||||||
"mq_timedsend",
|
"mq_timedsend",
|
||||||
|
"mq_timedsend_time64",
|
||||||
"mq_unlink",
|
"mq_unlink",
|
||||||
"mremap",
|
"mremap",
|
||||||
"msgctl",
|
"msgctl",
|
||||||
|
@ -216,18 +230,23 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
|
||||||
"_newselect",
|
"_newselect",
|
||||||
"open",
|
"open",
|
||||||
"openat",
|
"openat",
|
||||||
|
"openat2",
|
||||||
"pause",
|
"pause",
|
||||||
"pipe",
|
"pipe",
|
||||||
"pipe2",
|
"pipe2",
|
||||||
"poll",
|
"poll",
|
||||||
"ppoll",
|
"ppoll",
|
||||||
|
"ppoll_time64",
|
||||||
"prctl",
|
"prctl",
|
||||||
"pread64",
|
"pread64",
|
||||||
"preadv",
|
"preadv",
|
||||||
|
"preadv2",
|
||||||
"prlimit64",
|
"prlimit64",
|
||||||
"pselect6",
|
"pselect6",
|
||||||
|
"pselect6_time64",
|
||||||
"pwrite64",
|
"pwrite64",
|
||||||
"pwritev",
|
"pwritev",
|
||||||
|
"pwritev2",
|
||||||
"read",
|
"read",
|
||||||
"readahead",
|
"readahead",
|
||||||
"readlink",
|
"readlink",
|
||||||
|
@ -236,6 +255,7 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
|
||||||
"recv",
|
"recv",
|
||||||
"recvfrom",
|
"recvfrom",
|
||||||
"recvmmsg",
|
"recvmmsg",
|
||||||
|
"recvmmsg_time64",
|
||||||
"recvmsg",
|
"recvmsg",
|
||||||
"remap_file_pages",
|
"remap_file_pages",
|
||||||
"removexattr",
|
"removexattr",
|
||||||
|
@ -244,6 +264,7 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
|
||||||
"renameat2",
|
"renameat2",
|
||||||
"restart_syscall",
|
"restart_syscall",
|
||||||
"rmdir",
|
"rmdir",
|
||||||
|
"rseq",
|
||||||
"rt_sigaction",
|
"rt_sigaction",
|
||||||
"rt_sigpending",
|
"rt_sigpending",
|
||||||
"rt_sigprocmask",
|
"rt_sigprocmask",
|
||||||
|
@ -251,6 +272,7 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
|
||||||
"rt_sigreturn",
|
"rt_sigreturn",
|
||||||
"rt_sigsuspend",
|
"rt_sigsuspend",
|
||||||
"rt_sigtimedwait",
|
"rt_sigtimedwait",
|
||||||
|
"rt_sigtimedwait_time64",
|
||||||
"rt_tgsigqueueinfo",
|
"rt_tgsigqueueinfo",
|
||||||
"sched_getaffinity",
|
"sched_getaffinity",
|
||||||
"sched_getattr",
|
"sched_getattr",
|
||||||
|
@ -259,6 +281,7 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
|
||||||
"sched_get_priority_min",
|
"sched_get_priority_min",
|
||||||
"sched_getscheduler",
|
"sched_getscheduler",
|
||||||
"sched_rr_get_interval",
|
"sched_rr_get_interval",
|
||||||
|
"sched_rr_get_interval_time64",
|
||||||
"sched_setaffinity",
|
"sched_setaffinity",
|
||||||
"sched_setattr",
|
"sched_setattr",
|
||||||
"sched_setparam",
|
"sched_setparam",
|
||||||
|
@ -270,6 +293,7 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
|
||||||
"semget",
|
"semget",
|
||||||
"semop",
|
"semop",
|
||||||
"semtimedop",
|
"semtimedop",
|
||||||
|
"semtimedop_time64",
|
||||||
"send",
|
"send",
|
||||||
"sendfile",
|
"sendfile",
|
||||||
"sendfile64",
|
"sendfile64",
|
||||||
|
@ -329,18 +353,21 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
|
||||||
"sync_file_range",
|
"sync_file_range",
|
||||||
"syncfs",
|
"syncfs",
|
||||||
"sysinfo",
|
"sysinfo",
|
||||||
"syslog",
|
|
||||||
"tee",
|
"tee",
|
||||||
"tgkill",
|
"tgkill",
|
||||||
"time",
|
"time",
|
||||||
"timer_create",
|
"timer_create",
|
||||||
"timer_delete",
|
"timer_delete",
|
||||||
"timerfd_create",
|
|
||||||
"timerfd_gettime",
|
|
||||||
"timerfd_settime",
|
|
||||||
"timer_getoverrun",
|
"timer_getoverrun",
|
||||||
"timer_gettime",
|
"timer_gettime",
|
||||||
|
"timer_gettime64",
|
||||||
"timer_settime",
|
"timer_settime",
|
||||||
|
"timer_settime64",
|
||||||
|
"timerfd_create",
|
||||||
|
"timerfd_gettime",
|
||||||
|
"timerfd_gettime64",
|
||||||
|
"timerfd_settime",
|
||||||
|
"timerfd_settime64",
|
||||||
"times",
|
"times",
|
||||||
"tkill",
|
"tkill",
|
||||||
"truncate",
|
"truncate",
|
||||||
|
@ -352,6 +379,7 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
|
||||||
"unlinkat",
|
"unlinkat",
|
||||||
"utime",
|
"utime",
|
||||||
"utimensat",
|
"utimensat",
|
||||||
|
"utimensat_time64",
|
||||||
"utimes",
|
"utimes",
|
||||||
"vfork",
|
"vfork",
|
||||||
"vmsplice",
|
"vmsplice",
|
||||||
|
@ -386,6 +414,28 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Names: []string{"personality"},
|
||||||
|
Action: specs.ActAllow,
|
||||||
|
Args: []specs.LinuxSeccompArg{
|
||||||
|
{
|
||||||
|
Index: 0,
|
||||||
|
Value: 0x20000,
|
||||||
|
Op: specs.OpEqualTo,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Names: []string{"personality"},
|
||||||
|
Action: specs.ActAllow,
|
||||||
|
Args: []specs.LinuxSeccompArg{
|
||||||
|
{
|
||||||
|
Index: 0,
|
||||||
|
Value: 0x20008,
|
||||||
|
Op: specs.OpEqualTo,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Names: []string{"personality"},
|
Names: []string{"personality"},
|
||||||
Action: specs.ActAllow,
|
Action: specs.ActAllow,
|
||||||
|
@ -407,11 +457,20 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
|
||||||
|
|
||||||
// include by arch
|
// include by arch
|
||||||
switch runtime.GOARCH {
|
switch runtime.GOARCH {
|
||||||
|
case "ppc64le":
|
||||||
|
s.Syscalls = append(s.Syscalls, specs.LinuxSyscall{
|
||||||
|
Names: []string{
|
||||||
|
"sync_file_range2",
|
||||||
|
},
|
||||||
|
Action: specs.ActAllow,
|
||||||
|
Args: []specs.LinuxSeccompArg{},
|
||||||
|
})
|
||||||
case "arm", "arm64":
|
case "arm", "arm64":
|
||||||
s.Syscalls = append(s.Syscalls, specs.LinuxSyscall{
|
s.Syscalls = append(s.Syscalls, specs.LinuxSyscall{
|
||||||
Names: []string{
|
Names: []string{
|
||||||
"arm_fadvise64_64",
|
"arm_fadvise64_64",
|
||||||
"arm_sync_file_range",
|
"arm_sync_file_range",
|
||||||
|
"sync_file_range2",
|
||||||
"breakpoint",
|
"breakpoint",
|
||||||
"cacheflush",
|
"cacheflush",
|
||||||
"set_tls",
|
"set_tls",
|
||||||
|
@ -468,9 +527,11 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
|
||||||
"mount",
|
"mount",
|
||||||
"name_to_handle_at",
|
"name_to_handle_at",
|
||||||
"perf_event_open",
|
"perf_event_open",
|
||||||
|
"quotactl",
|
||||||
"setdomainname",
|
"setdomainname",
|
||||||
"sethostname",
|
"sethostname",
|
||||||
"setns",
|
"setns",
|
||||||
|
"syslog",
|
||||||
"umount",
|
"umount",
|
||||||
"umount2",
|
"umount2",
|
||||||
"unshare",
|
"unshare",
|
||||||
|
@ -496,7 +557,6 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
|
||||||
"delete_module",
|
"delete_module",
|
||||||
"init_module",
|
"init_module",
|
||||||
"finit_module",
|
"finit_module",
|
||||||
"query_module",
|
|
||||||
},
|
},
|
||||||
Action: specs.ActAllow,
|
Action: specs.ActAllow,
|
||||||
Args: []specs.LinuxSeccompArg{},
|
Args: []specs.LinuxSeccompArg{},
|
||||||
|
@ -532,7 +592,7 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
|
||||||
Names: []string{
|
Names: []string{
|
||||||
"settimeofday",
|
"settimeofday",
|
||||||
"stime",
|
"stime",
|
||||||
"adjtimex",
|
"clock_settime",
|
||||||
},
|
},
|
||||||
Action: specs.ActAllow,
|
Action: specs.ActAllow,
|
||||||
Args: []specs.LinuxSeccompArg{},
|
Args: []specs.LinuxSeccompArg{},
|
||||||
|
@ -543,6 +603,12 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
|
||||||
Action: specs.ActAllow,
|
Action: specs.ActAllow,
|
||||||
Args: []specs.LinuxSeccompArg{},
|
Args: []specs.LinuxSeccompArg{},
|
||||||
})
|
})
|
||||||
|
case "CAP_SYSLOG":
|
||||||
|
s.Syscalls = append(s.Syscalls, specs.LinuxSyscall{
|
||||||
|
Names: []string{"syslog"},
|
||||||
|
Action: specs.ActAllow,
|
||||||
|
Args: []specs.LinuxSeccompArg{},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ package seccomp
|
||||||
|
|
||||||
import specs "github.com/opencontainers/runtime-spec/specs-go"
|
import specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
|
||||||
// DefaultProfile defines the whitelist for the default seccomp profile.
|
// DefaultProfile defines the allowed syscalls for the default seccomp profile.
|
||||||
func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
|
func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
|
||||||
return &specs.LinuxSeccomp{}
|
return &specs.LinuxSeccomp{}
|
||||||
}
|
}
|
||||||
|
|
|
@ -209,6 +209,8 @@ func (p *parser) field() (string, error) {
|
||||||
return s, nil
|
return s, nil
|
||||||
case tokenQuoted:
|
case tokenQuoted:
|
||||||
return p.unquote(pos, s, false)
|
return p.unquote(pos, s, false)
|
||||||
|
case tokenIllegal:
|
||||||
|
return "", p.mkerr(pos, p.scanner.err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return "", p.mkerr(pos, "expected field or quoted")
|
return "", p.mkerr(pos, "expected field or quoted")
|
||||||
|
@ -228,6 +230,8 @@ func (p *parser) operator() (operator, error) {
|
||||||
default:
|
default:
|
||||||
return 0, p.mkerr(pos, "unsupported operator %q", s)
|
return 0, p.mkerr(pos, "unsupported operator %q", s)
|
||||||
}
|
}
|
||||||
|
case tokenIllegal:
|
||||||
|
return 0, p.mkerr(pos, p.scanner.err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0, p.mkerr(pos, `expected an operator ("=="|"!="|"~=")`)
|
return 0, p.mkerr(pos, `expected an operator ("=="|"!="|"~=")`)
|
||||||
|
@ -241,6 +245,8 @@ func (p *parser) value(allowAltQuotes bool) (string, error) {
|
||||||
return s, nil
|
return s, nil
|
||||||
case tokenQuoted:
|
case tokenQuoted:
|
||||||
return p.unquote(pos, s, allowAltQuotes)
|
return p.unquote(pos, s, allowAltQuotes)
|
||||||
|
case tokenIllegal:
|
||||||
|
return "", p.mkerr(pos, p.scanner.err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return "", p.mkerr(pos, "expected value or quoted")
|
return "", p.mkerr(pos, "expected value or quoted")
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
package filters
|
package filters
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"unicode"
|
"unicode"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
)
|
)
|
||||||
|
@ -64,6 +63,7 @@ type scanner struct {
|
||||||
pos int
|
pos int
|
||||||
ppos int // bounds the current rune in the string
|
ppos int // bounds the current rune in the string
|
||||||
value bool
|
value bool
|
||||||
|
err string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *scanner) init(input string) {
|
func (s *scanner) init(input string) {
|
||||||
|
@ -82,12 +82,14 @@ func (s *scanner) next() rune {
|
||||||
s.ppos += w
|
s.ppos += w
|
||||||
if r == utf8.RuneError {
|
if r == utf8.RuneError {
|
||||||
if w > 0 {
|
if w > 0 {
|
||||||
|
s.error("rune error")
|
||||||
return tokenIllegal
|
return tokenIllegal
|
||||||
}
|
}
|
||||||
return tokenEOF
|
return tokenEOF
|
||||||
}
|
}
|
||||||
|
|
||||||
if r == 0 {
|
if r == 0 {
|
||||||
|
s.error("unexpected null")
|
||||||
return tokenIllegal
|
return tokenIllegal
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +116,9 @@ chomp:
|
||||||
case ch == tokenEOF:
|
case ch == tokenEOF:
|
||||||
case ch == tokenIllegal:
|
case ch == tokenIllegal:
|
||||||
case isQuoteRune(ch):
|
case isQuoteRune(ch):
|
||||||
s.scanQuoted(ch)
|
if !s.scanQuoted(ch) {
|
||||||
|
return pos, tokenIllegal, s.input[pos:s.ppos]
|
||||||
|
}
|
||||||
return pos, tokenQuoted, s.input[pos:s.ppos]
|
return pos, tokenQuoted, s.input[pos:s.ppos]
|
||||||
case isSeparatorRune(ch):
|
case isSeparatorRune(ch):
|
||||||
s.value = false
|
s.value = false
|
||||||
|
@ -172,54 +176,64 @@ func (s *scanner) scanValue() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *scanner) scanQuoted(quote rune) {
|
func (s *scanner) scanQuoted(quote rune) bool {
|
||||||
|
var illegal bool
|
||||||
ch := s.next() // read character after quote
|
ch := s.next() // read character after quote
|
||||||
for ch != quote {
|
for ch != quote {
|
||||||
if ch == '\n' || ch < 0 {
|
if ch == '\n' || ch < 0 {
|
||||||
s.error("literal not terminated")
|
s.error("quoted literal not terminated")
|
||||||
return
|
return false
|
||||||
}
|
}
|
||||||
if ch == '\\' {
|
if ch == '\\' {
|
||||||
ch = s.scanEscape(quote)
|
var legal bool
|
||||||
|
ch, legal = s.scanEscape(quote)
|
||||||
|
if !legal {
|
||||||
|
illegal = true
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ch = s.next()
|
ch = s.next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return !illegal
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *scanner) scanEscape(quote rune) rune {
|
func (s *scanner) scanEscape(quote rune) (ch rune, legal bool) {
|
||||||
ch := s.next() // read character after '/'
|
ch = s.next() // read character after '/'
|
||||||
switch ch {
|
switch ch {
|
||||||
case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', quote:
|
case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', quote:
|
||||||
// nothing to do
|
// nothing to do
|
||||||
ch = s.next()
|
ch = s.next()
|
||||||
|
legal = true
|
||||||
case '0', '1', '2', '3', '4', '5', '6', '7':
|
case '0', '1', '2', '3', '4', '5', '6', '7':
|
||||||
ch = s.scanDigits(ch, 8, 3)
|
ch, legal = s.scanDigits(ch, 8, 3)
|
||||||
case 'x':
|
case 'x':
|
||||||
ch = s.scanDigits(s.next(), 16, 2)
|
ch, legal = s.scanDigits(s.next(), 16, 2)
|
||||||
case 'u':
|
case 'u':
|
||||||
ch = s.scanDigits(s.next(), 16, 4)
|
ch, legal = s.scanDigits(s.next(), 16, 4)
|
||||||
case 'U':
|
case 'U':
|
||||||
ch = s.scanDigits(s.next(), 16, 8)
|
ch, legal = s.scanDigits(s.next(), 16, 8)
|
||||||
default:
|
default:
|
||||||
s.error("illegal char escape")
|
s.error("illegal escape sequence")
|
||||||
}
|
}
|
||||||
return ch
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *scanner) scanDigits(ch rune, base, n int) rune {
|
func (s *scanner) scanDigits(ch rune, base, n int) (rune, bool) {
|
||||||
for n > 0 && digitVal(ch) < base {
|
for n > 0 && digitVal(ch) < base {
|
||||||
ch = s.next()
|
ch = s.next()
|
||||||
n--
|
n--
|
||||||
}
|
}
|
||||||
if n > 0 {
|
if n > 0 {
|
||||||
s.error("illegal char escape")
|
s.error("illegal numeric escape sequence")
|
||||||
|
return ch, false
|
||||||
}
|
}
|
||||||
return ch
|
return ch, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *scanner) error(msg string) {
|
func (s *scanner) error(msg string) {
|
||||||
fmt.Println("error fixme", msg)
|
if s.err == "" {
|
||||||
|
s.err = msg
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func digitVal(ch rune) int {
|
func digitVal(ch rune) int {
|
||||||
|
|
|
@ -197,6 +197,7 @@ func (i *image) Usage(ctx context.Context, opts ...UsageOpt) (int64, error) {
|
||||||
desc.Size = info.Size
|
desc.Size = info.Size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if config.snapshots {
|
||||||
for k, v := range info.Labels {
|
for k, v := range info.Labels {
|
||||||
const prefix = "containerd.io/gc.ref.snapshot."
|
const prefix = "containerd.io/gc.ref.snapshot."
|
||||||
if !strings.HasPrefix(k, prefix) {
|
if !strings.HasPrefix(k, prefix) {
|
||||||
|
@ -218,6 +219,7 @@ func (i *image) Usage(ctx context.Context, opts ...UsageOpt) (int64, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Ignore unknown sizes. Generally unknown sizes should
|
// Ignore unknown sizes. Generally unknown sizes should
|
||||||
// never be set in manifests, however, the usage
|
// never be set in manifests, however, the usage
|
||||||
|
|
|
@ -181,7 +181,7 @@ func ImportIndex(ctx context.Context, store content.Store, reader io.Reader, opt
|
||||||
Layers: layers,
|
Layers: layers,
|
||||||
}
|
}
|
||||||
|
|
||||||
desc, err := writeManifest(ctx, store, manifest, ocispec.MediaTypeImageManifest)
|
desc, err := writeManifest(ctx, store, manifest, manifest.MediaType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ocispec.Descriptor{}, errors.Wrap(err, "write docker manifest")
|
return ocispec.Descriptor{}, errors.Wrap(err, "write docker manifest")
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,8 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
|
||||||
introspectionapi "github.com/containerd/containerd/api/services/introspection/v1"
|
introspectionapi "github.com/containerd/containerd/api/services/introspection/v1"
|
||||||
"github.com/containerd/containerd/archive"
|
"github.com/containerd/containerd/archive"
|
||||||
|
@ -48,6 +50,15 @@ func (c *Client) Install(ctx context.Context, image Image, opts ...InstallOpts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var binDir, libDir string
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
binDir = "Files\\bin"
|
||||||
|
libDir = "Files\\lib"
|
||||||
|
} else {
|
||||||
|
binDir = "bin"
|
||||||
|
libDir = "lib"
|
||||||
|
}
|
||||||
for _, layer := range manifest.Layers {
|
for _, layer := range manifest.Layers {
|
||||||
ra, err := cs.ReaderAt(ctx, layer)
|
ra, err := cs.ReaderAt(ctx, layer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -60,9 +71,14 @@ func (c *Client) Install(ctx context.Context, image Image, opts ...InstallOpts)
|
||||||
}
|
}
|
||||||
if _, err := archive.Apply(ctx, path, r, archive.WithFilter(func(hdr *tar.Header) (bool, error) {
|
if _, err := archive.Apply(ctx, path, r, archive.WithFilter(func(hdr *tar.Header) (bool, error) {
|
||||||
d := filepath.Dir(hdr.Name)
|
d := filepath.Dir(hdr.Name)
|
||||||
result := d == "bin"
|
result := d == binDir
|
||||||
|
|
||||||
if config.Libs {
|
if config.Libs {
|
||||||
result = result || d == "lib"
|
result = result || d == libDir
|
||||||
|
}
|
||||||
|
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
hdr.Name = strings.Replace(hdr.Name, "Files", "", 1)
|
||||||
}
|
}
|
||||||
if result && !config.Replace {
|
if result && !config.Replace {
|
||||||
if _, err := os.Lstat(filepath.Join(path, hdr.Name)); err == nil {
|
if _, err := os.Lstat(filepath.Join(path, hdr.Name)); err == nil {
|
||||||
|
|
|
@ -69,3 +69,7 @@ func (s *deletedState) SetExited(status int) {
|
||||||
func (s *deletedState) Exec(ctx context.Context, path string, r *ExecConfig) (Process, error) {
|
func (s *deletedState) Exec(ctx context.Context, path string, r *ExecConfig) (Process, error) {
|
||||||
return nil, errors.Errorf("cannot exec in a deleted state")
|
return nil, errors.Errorf("cannot exec in a deleted state")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *deletedState) Status(ctx context.Context) (string, error) {
|
||||||
|
return "stopped", nil
|
||||||
|
}
|
||||||
|
|
|
@ -96,7 +96,6 @@ func (e *execProcess) setExited(status int) {
|
||||||
e.status = status
|
e.status = status
|
||||||
e.exited = time.Now()
|
e.exited = time.Now()
|
||||||
e.parent.Platform.ShutdownConsole(context.Background(), e.console)
|
e.parent.Platform.ShutdownConsole(context.Background(), e.console)
|
||||||
e.pid.set(StoppedPID)
|
|
||||||
close(e.waitBlock)
|
close(e.waitBlock)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,7 +146,7 @@ func (e *execProcess) kill(ctx context.Context, sig uint32, _ bool) error {
|
||||||
switch {
|
switch {
|
||||||
case pid == 0:
|
case pid == 0:
|
||||||
return errors.Wrap(errdefs.ErrFailedPrecondition, "process not created")
|
return errors.Wrap(errdefs.ErrFailedPrecondition, "process not created")
|
||||||
case pid < 0:
|
case !e.exited.IsZero():
|
||||||
return errors.Wrapf(errdefs.ErrNotFound, "process already finished")
|
return errors.Wrapf(errdefs.ErrNotFound, "process already finished")
|
||||||
default:
|
default:
|
||||||
if err := unix.Kill(pid, syscall.Signal(sig)); err != nil {
|
if err := unix.Kill(pid, syscall.Signal(sig)); err != nil {
|
||||||
|
@ -261,17 +260,5 @@ func (e *execProcess) Status(ctx context.Context) (string, error) {
|
||||||
}
|
}
|
||||||
e.mu.Lock()
|
e.mu.Lock()
|
||||||
defer e.mu.Unlock()
|
defer e.mu.Unlock()
|
||||||
// if we don't have a pid(pid=0) then the exec process has just been created
|
return e.execState.Status(ctx)
|
||||||
if e.pid.get() == 0 {
|
|
||||||
return "created", nil
|
|
||||||
}
|
|
||||||
if e.pid.get() == StoppedPID {
|
|
||||||
return "stopped", nil
|
|
||||||
}
|
|
||||||
// if we have a pid and it can be signaled, the process is running
|
|
||||||
if err := unix.Kill(e.pid.get(), 0); err == nil {
|
|
||||||
return "running", nil
|
|
||||||
}
|
|
||||||
// else if we have a pid but it can nolonger be signaled, it has stopped
|
|
||||||
return "stopped", nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,7 @@ type execState interface {
|
||||||
Delete(context.Context) error
|
Delete(context.Context) error
|
||||||
Kill(context.Context, uint32, bool) error
|
Kill(context.Context, uint32, bool) error
|
||||||
SetExited(int)
|
SetExited(int)
|
||||||
|
Status(context.Context) (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type execCreatedState struct {
|
type execCreatedState struct {
|
||||||
|
@ -82,6 +83,10 @@ func (s *execCreatedState) SetExited(status int) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *execCreatedState) Status(ctx context.Context) (string, error) {
|
||||||
|
return "created", nil
|
||||||
|
}
|
||||||
|
|
||||||
type execRunningState struct {
|
type execRunningState struct {
|
||||||
p *execProcess
|
p *execProcess
|
||||||
}
|
}
|
||||||
|
@ -120,6 +125,10 @@ func (s *execRunningState) SetExited(status int) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *execRunningState) Status(ctx context.Context) (string, error) {
|
||||||
|
return "running", nil
|
||||||
|
}
|
||||||
|
|
||||||
type execStoppedState struct {
|
type execStoppedState struct {
|
||||||
p *execProcess
|
p *execProcess
|
||||||
}
|
}
|
||||||
|
@ -157,3 +166,7 @@ func (s *execStoppedState) Kill(ctx context.Context, sig uint32, all bool) error
|
||||||
func (s *execStoppedState) SetExited(status int) {
|
func (s *execStoppedState) SetExited(status int) {
|
||||||
// no op
|
// no op
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *execStoppedState) Status(ctx context.Context) (string, error) {
|
||||||
|
return "stopped", nil
|
||||||
|
}
|
||||||
|
|
|
@ -62,9 +62,11 @@ type Init struct {
|
||||||
Platform stdio.Platform
|
Platform stdio.Platform
|
||||||
io *processIO
|
io *processIO
|
||||||
runtime *runc.Runc
|
runtime *runc.Runc
|
||||||
|
// pausing preserves the pausing state.
|
||||||
|
pausing *atomicBool
|
||||||
status int
|
status int
|
||||||
exited time.Time
|
exited time.Time
|
||||||
pid safePid
|
pid int
|
||||||
closers []io.Closer
|
closers []io.Closer
|
||||||
stdin io.Closer
|
stdin io.Closer
|
||||||
stdio stdio.Stdio
|
stdio stdio.Stdio
|
||||||
|
@ -97,6 +99,7 @@ func New(id string, runtime *runc.Runc, stdio stdio.Stdio) *Init {
|
||||||
p := &Init{
|
p := &Init{
|
||||||
id: id,
|
id: id,
|
||||||
runtime: runtime,
|
runtime: runtime,
|
||||||
|
pausing: new(atomicBool),
|
||||||
stdio: stdio,
|
stdio: stdio,
|
||||||
status: 0,
|
status: 0,
|
||||||
waitBlock: make(chan struct{}),
|
waitBlock: make(chan struct{}),
|
||||||
|
@ -113,8 +116,6 @@ func (p *Init) Create(ctx context.Context, r *CreateConfig) error {
|
||||||
pio *processIO
|
pio *processIO
|
||||||
pidFile = newPidFile(p.Bundle)
|
pidFile = newPidFile(p.Bundle)
|
||||||
)
|
)
|
||||||
p.pid.Lock()
|
|
||||||
defer p.pid.Unlock()
|
|
||||||
|
|
||||||
if r.Terminal {
|
if r.Terminal {
|
||||||
if socket, err = runc.NewTempConsoleSocket(); err != nil {
|
if socket, err = runc.NewTempConsoleSocket(); err != nil {
|
||||||
|
@ -170,7 +171,7 @@ func (p *Init) Create(ctx context.Context, r *CreateConfig) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "failed to retrieve OCI runtime container pid")
|
return errors.Wrap(err, "failed to retrieve OCI runtime container pid")
|
||||||
}
|
}
|
||||||
p.pid.pid = pid
|
p.pid = pid
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,7 +217,7 @@ func (p *Init) ID() string {
|
||||||
|
|
||||||
// Pid of the process
|
// Pid of the process
|
||||||
func (p *Init) Pid() int {
|
func (p *Init) Pid() int {
|
||||||
return p.pid.get()
|
return p.pid
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExitStatus of the process
|
// ExitStatus of the process
|
||||||
|
@ -237,17 +238,14 @@ func (p *Init) ExitedAt() time.Time {
|
||||||
|
|
||||||
// Status of the process
|
// Status of the process
|
||||||
func (p *Init) Status(ctx context.Context) (string, error) {
|
func (p *Init) Status(ctx context.Context) (string, error) {
|
||||||
|
if p.pausing.get() {
|
||||||
|
return "pausing", nil
|
||||||
|
}
|
||||||
|
|
||||||
p.mu.Lock()
|
p.mu.Lock()
|
||||||
defer p.mu.Unlock()
|
defer p.mu.Unlock()
|
||||||
|
|
||||||
c, err := p.runtime.State(ctx, p.id)
|
return p.initState.Status(ctx)
|
||||||
if err != nil {
|
|
||||||
if strings.Contains(err.Error(), "does not exist") {
|
|
||||||
return "stopped", nil
|
|
||||||
}
|
|
||||||
return "", p.runtimeError(err, "OCI runtime state failed")
|
|
||||||
}
|
|
||||||
return c.Status, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start the init process
|
// Start the init process
|
||||||
|
@ -275,7 +273,6 @@ func (p *Init) setExited(status int) {
|
||||||
p.exited = time.Now()
|
p.exited = time.Now()
|
||||||
p.status = status
|
p.status = status
|
||||||
p.Platform.ShutdownConsole(context.Background(), p.console)
|
p.Platform.ShutdownConsole(context.Background(), p.console)
|
||||||
p.pid.set(StoppedPID)
|
|
||||||
close(p.waitBlock)
|
close(p.waitBlock)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ type initState interface {
|
||||||
Exec(context.Context, string, *ExecConfig) (Process, error)
|
Exec(context.Context, string, *ExecConfig) (Process, error)
|
||||||
Kill(context.Context, uint32, bool) error
|
Kill(context.Context, uint32, bool) error
|
||||||
SetExited(int)
|
SetExited(int)
|
||||||
|
Status(context.Context) (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type createdState struct {
|
type createdState struct {
|
||||||
|
@ -103,6 +104,10 @@ func (s *createdState) Exec(ctx context.Context, path string, r *ExecConfig) (Pr
|
||||||
return s.p.exec(ctx, path, r)
|
return s.p.exec(ctx, path, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *createdState) Status(ctx context.Context) (string, error) {
|
||||||
|
return "created", nil
|
||||||
|
}
|
||||||
|
|
||||||
type createdCheckpointState struct {
|
type createdCheckpointState struct {
|
||||||
p *Init
|
p *Init
|
||||||
opts *runc.RestoreOpts
|
opts *runc.RestoreOpts
|
||||||
|
@ -142,9 +147,6 @@ func (s *createdCheckpointState) Start(ctx context.Context) error {
|
||||||
p := s.p
|
p := s.p
|
||||||
sio := p.stdio
|
sio := p.stdio
|
||||||
|
|
||||||
p.pid.Lock()
|
|
||||||
defer p.pid.Unlock()
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
socket *runc.Socket
|
socket *runc.Socket
|
||||||
|
@ -184,7 +186,7 @@ func (s *createdCheckpointState) Start(ctx context.Context) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "failed to retrieve OCI runtime container pid")
|
return errors.Wrap(err, "failed to retrieve OCI runtime container pid")
|
||||||
}
|
}
|
||||||
p.pid.pid = pid
|
p.pid = pid
|
||||||
return s.transition("running")
|
return s.transition("running")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,6 +213,10 @@ func (s *createdCheckpointState) Exec(ctx context.Context, path string, r *ExecC
|
||||||
return nil, errors.Errorf("cannot exec in a created state")
|
return nil, errors.Errorf("cannot exec in a created state")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *createdCheckpointState) Status(ctx context.Context) (string, error) {
|
||||||
|
return "created", nil
|
||||||
|
}
|
||||||
|
|
||||||
type runningState struct {
|
type runningState struct {
|
||||||
p *Init
|
p *Init
|
||||||
}
|
}
|
||||||
|
@ -228,6 +234,13 @@ func (s *runningState) transition(name string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *runningState) Pause(ctx context.Context) error {
|
func (s *runningState) Pause(ctx context.Context) error {
|
||||||
|
s.p.pausing.set(true)
|
||||||
|
// NOTE "pausing" will be returned in the short window
|
||||||
|
// after `transition("paused")`, before `pausing` is reset
|
||||||
|
// to false. That doesn't break the state machine, just
|
||||||
|
// delays the "paused" state a little bit.
|
||||||
|
defer s.p.pausing.set(false)
|
||||||
|
|
||||||
if err := s.p.runtime.Pause(ctx, s.p.id); err != nil {
|
if err := s.p.runtime.Pause(ctx, s.p.id); err != nil {
|
||||||
return s.p.runtimeError(err, "OCI runtime pause failed")
|
return s.p.runtimeError(err, "OCI runtime pause failed")
|
||||||
}
|
}
|
||||||
|
@ -271,6 +284,10 @@ func (s *runningState) Exec(ctx context.Context, path string, r *ExecConfig) (Pr
|
||||||
return s.p.exec(ctx, path, r)
|
return s.p.exec(ctx, path, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *runningState) Status(ctx context.Context) (string, error) {
|
||||||
|
return "running", nil
|
||||||
|
}
|
||||||
|
|
||||||
type pausedState struct {
|
type pausedState struct {
|
||||||
p *Init
|
p *Init
|
||||||
}
|
}
|
||||||
|
@ -335,6 +352,10 @@ func (s *pausedState) Exec(ctx context.Context, path string, r *ExecConfig) (Pro
|
||||||
return nil, errors.Errorf("cannot exec in a paused state")
|
return nil, errors.Errorf("cannot exec in a paused state")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *pausedState) Status(ctx context.Context) (string, error) {
|
||||||
|
return "paused", nil
|
||||||
|
}
|
||||||
|
|
||||||
type stoppedState struct {
|
type stoppedState struct {
|
||||||
p *Init
|
p *Init
|
||||||
}
|
}
|
||||||
|
@ -387,3 +408,7 @@ func (s *stoppedState) SetExited(status int) {
|
||||||
func (s *stoppedState) Exec(ctx context.Context, path string, r *ExecConfig) (Process, error) {
|
func (s *stoppedState) Exec(ctx context.Context, path string, r *ExecConfig) (Process, error) {
|
||||||
return nil, errors.Errorf("cannot exec in a stopped state")
|
return nil, errors.Errorf("cannot exec in a stopped state")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *stoppedState) Status(ctx context.Context) (string, error) {
|
||||||
|
return "stopped", nil
|
||||||
|
}
|
||||||
|
|
|
@ -29,15 +29,20 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/containerd/containerd/log"
|
"github.com/containerd/containerd/log"
|
||||||
"github.com/containerd/containerd/namespaces"
|
"github.com/containerd/containerd/namespaces"
|
||||||
"github.com/containerd/containerd/pkg/stdio"
|
"github.com/containerd/containerd/pkg/stdio"
|
||||||
|
"github.com/containerd/containerd/sys"
|
||||||
"github.com/containerd/fifo"
|
"github.com/containerd/fifo"
|
||||||
runc "github.com/containerd/go-runc"
|
runc "github.com/containerd/go-runc"
|
||||||
|
"github.com/hashicorp/go-multierror"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const binaryIOProcTermTimeout = 12 * time.Second // Give logger process solid 10 seconds for cleanup
|
||||||
|
|
||||||
var bufPool = sync.Pool{
|
var bufPool = sync.Pool{
|
||||||
New: func() interface{} {
|
New: func() interface{} {
|
||||||
// setting to 4096 to align with PIPE_BUF
|
// setting to 4096 to align with PIPE_BUF
|
||||||
|
@ -174,7 +179,7 @@ func copyPipes(ctx context.Context, rio runc.IO, stdin, stdout, stderr string, w
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
ok, err := isFifo(i.name)
|
ok, err := sys.IsFifo(i.name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -240,28 +245,13 @@ func (c *countingWriteCloser) Close() error {
|
||||||
return c.WriteCloser.Close()
|
return c.WriteCloser.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// isFifo checks if a file is a fifo
|
|
||||||
// if the file does not exist then it returns false
|
|
||||||
func isFifo(path string) (bool, error) {
|
|
||||||
stat, err := os.Stat(path)
|
|
||||||
if err != nil {
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
if stat.Mode()&os.ModeNamedPipe == os.ModeNamedPipe {
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewBinaryIO runs a custom binary process for pluggable shim logging
|
// NewBinaryIO runs a custom binary process for pluggable shim logging
|
||||||
func NewBinaryIO(ctx context.Context, id string, uri *url.URL) (runc.IO, error) {
|
func NewBinaryIO(ctx context.Context, id string, uri *url.URL) (_ runc.IO, err error) {
|
||||||
ns, err := namespaces.NamespaceRequired(ctx)
|
ns, err := namespaces.NamespaceRequired(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var args []string
|
var args []string
|
||||||
for k, vs := range uri.Query() {
|
for k, vs := range uri.Query() {
|
||||||
args = append(args, k)
|
args = append(args, k)
|
||||||
|
@ -269,48 +259,64 @@ func NewBinaryIO(ctx context.Context, id string, uri *url.URL) (runc.IO, error)
|
||||||
args = append(args, vs[0])
|
args = append(args, vs[0])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctx, cancel := context.WithCancel(ctx)
|
|
||||||
cmd := exec.CommandContext(ctx, uri.Path, args...)
|
var closers []func() error
|
||||||
|
defer func() {
|
||||||
|
if err == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
result := multierror.Append(err)
|
||||||
|
for _, fn := range closers {
|
||||||
|
result = multierror.Append(result, fn())
|
||||||
|
}
|
||||||
|
err = multierror.Flatten(result)
|
||||||
|
}()
|
||||||
|
|
||||||
|
out, err := newPipe()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to create stdout pipes")
|
||||||
|
}
|
||||||
|
closers = append(closers, out.Close)
|
||||||
|
|
||||||
|
serr, err := newPipe()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to create stderr pipes")
|
||||||
|
}
|
||||||
|
closers = append(closers, serr.Close)
|
||||||
|
|
||||||
|
r, w, err := os.Pipe()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
closers = append(closers, r.Close, w.Close)
|
||||||
|
|
||||||
|
cmd := exec.Command(uri.Path, args...)
|
||||||
cmd.Env = append(cmd.Env,
|
cmd.Env = append(cmd.Env,
|
||||||
"CONTAINER_ID="+id,
|
"CONTAINER_ID="+id,
|
||||||
"CONTAINER_NAMESPACE="+ns,
|
"CONTAINER_NAMESPACE="+ns,
|
||||||
)
|
)
|
||||||
out, err := newPipe()
|
|
||||||
if err != nil {
|
|
||||||
cancel()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
serr, err := newPipe()
|
|
||||||
if err != nil {
|
|
||||||
cancel()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
r, w, err := os.Pipe()
|
|
||||||
if err != nil {
|
|
||||||
cancel()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
cmd.ExtraFiles = append(cmd.ExtraFiles, out.r, serr.r, w)
|
cmd.ExtraFiles = append(cmd.ExtraFiles, out.r, serr.r, w)
|
||||||
// don't need to register this with the reaper or wait when
|
// don't need to register this with the reaper or wait when
|
||||||
// running inside a shim
|
// running inside a shim
|
||||||
if err := cmd.Start(); err != nil {
|
if err := cmd.Start(); err != nil {
|
||||||
cancel()
|
return nil, errors.Wrap(err, "failed to start binary process")
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
closers = append(closers, func() error { return cmd.Process.Kill() })
|
||||||
|
|
||||||
// close our side of the pipe after start
|
// close our side of the pipe after start
|
||||||
if err := w.Close(); err != nil {
|
if err := w.Close(); err != nil {
|
||||||
cancel()
|
return nil, errors.Wrap(err, "failed to close write pipe after start")
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait for the logging binary to be ready
|
// wait for the logging binary to be ready
|
||||||
b := make([]byte, 1)
|
b := make([]byte, 1)
|
||||||
if _, err := r.Read(b); err != nil && err != io.EOF {
|
if _, err := r.Read(b); err != nil && err != io.EOF {
|
||||||
cancel()
|
return nil, errors.Wrap(err, "failed to read from logging binary")
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &binaryIO{
|
return &binaryIO{
|
||||||
cmd: cmd,
|
cmd: cmd,
|
||||||
cancel: cancel,
|
|
||||||
out: out,
|
out: out,
|
||||||
err: serr,
|
err: serr,
|
||||||
}, nil
|
}, nil
|
||||||
|
@ -318,37 +324,81 @@ func NewBinaryIO(ctx context.Context, id string, uri *url.URL) (runc.IO, error)
|
||||||
|
|
||||||
type binaryIO struct {
|
type binaryIO struct {
|
||||||
cmd *exec.Cmd
|
cmd *exec.Cmd
|
||||||
cancel func()
|
|
||||||
out, err *pipe
|
out, err *pipe
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *binaryIO) CloseAfterStart() (err error) {
|
func (b *binaryIO) CloseAfterStart() error {
|
||||||
for _, v := range []*pipe{
|
var (
|
||||||
b.out,
|
result *multierror.Error
|
||||||
b.err,
|
)
|
||||||
} {
|
|
||||||
|
for _, v := range []*pipe{b.out, b.err} {
|
||||||
if v != nil {
|
if v != nil {
|
||||||
if cerr := v.r.Close(); err == nil {
|
if err := v.r.Close(); err != nil {
|
||||||
err = cerr
|
result = multierror.Append(result, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return err
|
|
||||||
|
return result.ErrorOrNil()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *binaryIO) Close() (err error) {
|
func (b *binaryIO) Close() error {
|
||||||
b.cancel()
|
var (
|
||||||
for _, v := range []*pipe{
|
result *multierror.Error
|
||||||
b.out,
|
)
|
||||||
b.err,
|
|
||||||
} {
|
for _, v := range []*pipe{b.out, b.err} {
|
||||||
if v != nil {
|
if v != nil {
|
||||||
if cerr := v.Close(); err == nil {
|
if err := v.Close(); err != nil {
|
||||||
err = cerr
|
result = multierror.Append(result, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := b.cancel(); err != nil {
|
||||||
|
result = multierror.Append(result, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.ErrorOrNil()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *binaryIO) cancel() error {
|
||||||
|
if b.cmd == nil || b.cmd.Process == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send SIGTERM first, so logger process has a chance to flush and exit properly
|
||||||
|
if err := b.cmd.Process.Signal(syscall.SIGTERM); err != nil {
|
||||||
|
result := multierror.Append(errors.Wrap(err, "failed to send SIGTERM"))
|
||||||
|
|
||||||
|
log.L.WithError(err).Warn("failed to send SIGTERM signal, killing logging shim")
|
||||||
|
|
||||||
|
if err := b.cmd.Process.Kill(); err != nil {
|
||||||
|
result = multierror.Append(result, errors.Wrap(err, "failed to kill process after faulty SIGTERM"))
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.ErrorOrNil()
|
||||||
|
}
|
||||||
|
|
||||||
|
done := make(chan error)
|
||||||
|
go func() {
|
||||||
|
done <- b.cmd.Wait()
|
||||||
|
}()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case err := <-done:
|
||||||
return err
|
return err
|
||||||
|
case <-time.After(binaryIOProcTermTimeout):
|
||||||
|
log.L.Warn("failed to wait for shim logger process to exit, killing")
|
||||||
|
|
||||||
|
err := b.cmd.Process.Kill()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "failed to kill shim logger process")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *binaryIO) Stdin() io.WriteCloser {
|
func (b *binaryIO) Stdin() io.WriteCloser {
|
||||||
|
@ -389,9 +439,15 @@ type pipe struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *pipe) Close() error {
|
func (p *pipe) Close() error {
|
||||||
err := p.w.Close()
|
var result *multierror.Error
|
||||||
if rerr := p.r.Close(); err == nil {
|
|
||||||
err = rerr
|
if err := p.w.Close(); err != nil {
|
||||||
|
result = multierror.Append(result, errors.Wrap(err, "failed to close write pipe"))
|
||||||
}
|
}
|
||||||
return err
|
|
||||||
|
if err := p.r.Close(); err != nil {
|
||||||
|
result = multierror.Append(result, errors.Wrap(err, "failed to close read pipe"))
|
||||||
|
}
|
||||||
|
|
||||||
|
return multierror.Prefix(result.ErrorOrNil(), "pipe:")
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containerd/containerd/errdefs"
|
"github.com/containerd/containerd/errdefs"
|
||||||
|
@ -38,8 +39,6 @@ import (
|
||||||
const (
|
const (
|
||||||
// RuncRoot is the path to the root runc state directory
|
// RuncRoot is the path to the root runc state directory
|
||||||
RuncRoot = "/run/containerd/runc"
|
RuncRoot = "/run/containerd/runc"
|
||||||
// StoppedPID is the pid assigned after a container has run and stopped
|
|
||||||
StoppedPID = -1
|
|
||||||
// InitPidFile name of the file that contains the init pid
|
// InitPidFile name of the file that contains the init pid
|
||||||
InitPidFile = "init.pid"
|
InitPidFile = "init.pid"
|
||||||
)
|
)
|
||||||
|
@ -56,10 +55,18 @@ func (s *safePid) get() int {
|
||||||
return s.pid
|
return s.pid
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *safePid) set(pid int) {
|
type atomicBool int32
|
||||||
s.Lock()
|
|
||||||
s.pid = pid
|
func (ab *atomicBool) set(b bool) {
|
||||||
s.Unlock()
|
if b {
|
||||||
|
atomic.StoreInt32((*int32)(ab), 1)
|
||||||
|
} else {
|
||||||
|
atomic.StoreInt32((*int32)(ab), 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ab *atomicBool) get() bool {
|
||||||
|
return atomic.LoadInt32((*int32)(ab)) == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(mlaventure): move to runc package?
|
// TODO(mlaventure): move to runc package?
|
||||||
|
@ -130,6 +137,8 @@ func checkKillError(err error) error {
|
||||||
strings.Contains(strings.ToLower(err.Error()), "no such process") ||
|
strings.Contains(strings.ToLower(err.Error()), "no such process") ||
|
||||||
err == unix.ESRCH {
|
err == unix.ESRCH {
|
||||||
return errors.Wrapf(errdefs.ErrNotFound, "process already finished")
|
return errors.Wrapf(errdefs.ErrNotFound, "process already finished")
|
||||||
|
} else if strings.Contains(err.Error(), "does not exist") {
|
||||||
|
return errors.Wrapf(errdefs.ErrNotFound, "no such container")
|
||||||
}
|
}
|
||||||
return errors.Wrapf(err, "unknown error after kill")
|
return errors.Wrapf(err, "unknown error after kill")
|
||||||
}
|
}
|
||||||
|
|
|
@ -189,9 +189,8 @@ func Parse(specifier string) (specs.Platform, error) {
|
||||||
if isKnownOS(p.OS) {
|
if isKnownOS(p.OS) {
|
||||||
// picks a default architecture
|
// picks a default architecture
|
||||||
p.Architecture = runtime.GOARCH
|
p.Architecture = runtime.GOARCH
|
||||||
if p.Architecture == "arm" {
|
if p.Architecture == "arm" && cpuVariant != "v7" {
|
||||||
// TODO(stevvooe): Resolve arm variant, if not v6 (default)
|
p.Variant = cpuVariant
|
||||||
return specs.Platform{}, errors.Wrapf(errdefs.ErrNotImplemented, "arm support not fully implemented")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return p, nil
|
return p, nil
|
||||||
|
|
|
@ -70,6 +70,11 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (_ Ima
|
||||||
}
|
}
|
||||||
unpackWrapper, eg := u.handlerWrapper(ctx, &unpacks)
|
unpackWrapper, eg := u.handlerWrapper(ctx, &unpacks)
|
||||||
defer func() {
|
defer func() {
|
||||||
|
if retErr != nil {
|
||||||
|
// Forcibly stop the unpacker if there is
|
||||||
|
// an error.
|
||||||
|
eg.Cancel()
|
||||||
|
}
|
||||||
if err := eg.Wait(); err != nil {
|
if err := eg.Wait(); err != nil {
|
||||||
if retErr == nil {
|
if retErr == nil {
|
||||||
retErr = errors.Wrap(err, "unpack")
|
retErr = errors.Wrap(err, "unpack")
|
||||||
|
|
|
@ -96,41 +96,49 @@ func (r dockerFetcher) Fetch(ctx context.Context, desc ocispec.Descriptor) (io.R
|
||||||
images.MediaTypeDockerSchema1Manifest,
|
images.MediaTypeDockerSchema1Manifest,
|
||||||
ocispec.MediaTypeImageManifest, ocispec.MediaTypeImageIndex:
|
ocispec.MediaTypeImageManifest, ocispec.MediaTypeImageIndex:
|
||||||
|
|
||||||
|
var firstErr error
|
||||||
for _, host := range r.hosts {
|
for _, host := range r.hosts {
|
||||||
req := r.request(host, http.MethodGet, "manifests", desc.Digest.String())
|
req := r.request(host, http.MethodGet, "manifests", desc.Digest.String())
|
||||||
|
|
||||||
rc, err := r.open(ctx, req, desc.MediaType, offset)
|
rc, err := r.open(ctx, req, desc.MediaType, offset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errdefs.IsNotFound(err) {
|
// Store the error for referencing later
|
||||||
continue // try another host
|
if firstErr == nil {
|
||||||
|
firstErr = err
|
||||||
}
|
}
|
||||||
|
continue // try another host
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc, nil
|
return rc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil, firstErr
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally use blobs endpoints
|
// Finally use blobs endpoints
|
||||||
|
var firstErr error
|
||||||
for _, host := range r.hosts {
|
for _, host := range r.hosts {
|
||||||
req := r.request(host, http.MethodGet, "blobs", desc.Digest.String())
|
req := r.request(host, http.MethodGet, "blobs", desc.Digest.String())
|
||||||
|
|
||||||
rc, err := r.open(ctx, req, desc.MediaType, offset)
|
rc, err := r.open(ctx, req, desc.MediaType, offset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errdefs.IsNotFound(err) {
|
// Store the error for referencing later
|
||||||
continue // try another host
|
if firstErr == nil {
|
||||||
|
firstErr = err
|
||||||
}
|
}
|
||||||
|
continue // try another host
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc, nil
|
return rc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, errors.Wrapf(errdefs.ErrNotFound,
|
if errdefs.IsNotFound(firstErr) {
|
||||||
|
firstErr = errors.Wrapf(errdefs.ErrNotFound,
|
||||||
"could not fetch content descriptor %v (%v) from remote",
|
"could not fetch content descriptor %v (%v) from remote",
|
||||||
desc.Digest, desc.MediaType)
|
desc.Digest, desc.MediaType)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, firstErr
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -204,6 +204,7 @@ func (p dockerPusher) Push(ctx context.Context, desc ocispec.Descriptor) (conten
|
||||||
q.Add("digest", desc.Digest.String())
|
q.Add("digest", desc.Digest.String())
|
||||||
|
|
||||||
req = p.request(lhost, http.MethodPut)
|
req = p.request(lhost, http.MethodPut)
|
||||||
|
req.header.Set("Content-Type", "application/octet-stream")
|
||||||
req.path = lurl.Path + "?" + q.Encode()
|
req.path = lurl.Path + "?" + q.Encode()
|
||||||
}
|
}
|
||||||
p.tracker.SetStatus(ref, Status{
|
p.tracker.SetStatus(ref, Status{
|
||||||
|
|
|
@ -286,7 +286,11 @@ func (r *dockerResolver) Resolve(ctx context.Context, ref string) (string, ocisp
|
||||||
if errors.Cause(err) == ErrInvalidAuthorization {
|
if errors.Cause(err) == ErrInvalidAuthorization {
|
||||||
err = errors.Wrapf(err, "pull access denied, repository does not exist or may require authorization")
|
err = errors.Wrapf(err, "pull access denied, repository does not exist or may require authorization")
|
||||||
}
|
}
|
||||||
return "", ocispec.Descriptor{}, err
|
// Store the error for referencing later
|
||||||
|
if lastErr == nil {
|
||||||
|
lastErr = err
|
||||||
|
}
|
||||||
|
continue // try another host
|
||||||
}
|
}
|
||||||
resp.Body.Close() // don't care about body contents.
|
resp.Body.Close() // don't care about body contents.
|
||||||
|
|
||||||
|
|
|
@ -91,7 +91,7 @@ func ShimRemote(c *Config, daemonAddress, cgroup string, exitHandler func()) Shi
|
||||||
return func(b *bundle, ns string, ropts *runctypes.RuncOptions) (shim.Config, client.Opt) {
|
return func(b *bundle, ns string, ropts *runctypes.RuncOptions) (shim.Config, client.Opt) {
|
||||||
config := b.shimConfig(ns, c, ropts)
|
config := b.shimConfig(ns, c, ropts)
|
||||||
return config,
|
return config,
|
||||||
client.WithStart(c.Shim, b.shimAddress(ns), daemonAddress, cgroup, c.ShimDebug, exitHandler)
|
client.WithStart(c.Shim, b.shimAddress(ns, daemonAddress), daemonAddress, cgroup, c.ShimDebug, exitHandler)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,6 +117,11 @@ func (b *bundle) NewShimClient(ctx context.Context, namespace string, getClientO
|
||||||
|
|
||||||
// Delete deletes the bundle from disk
|
// Delete deletes the bundle from disk
|
||||||
func (b *bundle) Delete() error {
|
func (b *bundle) Delete() error {
|
||||||
|
address, _ := b.loadAddress()
|
||||||
|
if address != "" {
|
||||||
|
// we don't care about errors here
|
||||||
|
client.RemoveSocket(address)
|
||||||
|
}
|
||||||
err := atomicDelete(b.path)
|
err := atomicDelete(b.path)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return atomicDelete(b.workDir)
|
return atomicDelete(b.workDir)
|
||||||
|
@ -133,9 +138,11 @@ func (b *bundle) legacyShimAddress(namespace string) string {
|
||||||
return filepath.Join(string(filepath.Separator), "containerd-shim", namespace, b.id, "shim.sock")
|
return filepath.Join(string(filepath.Separator), "containerd-shim", namespace, b.id, "shim.sock")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *bundle) shimAddress(namespace string) string {
|
const socketRoot = "/run/containerd"
|
||||||
d := sha256.Sum256([]byte(filepath.Join(namespace, b.id)))
|
|
||||||
return filepath.Join(string(filepath.Separator), "containerd-shim", fmt.Sprintf("%x.sock", d))
|
func (b *bundle) shimAddress(namespace, socketPath string) string {
|
||||||
|
d := sha256.Sum256([]byte(filepath.Join(socketPath, namespace, b.id)))
|
||||||
|
return fmt.Sprintf("unix://%s/%x", filepath.Join(socketRoot, "s"), d)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *bundle) loadAddress() (string, error) {
|
func (b *bundle) loadAddress() (string, error) {
|
||||||
|
|
|
@ -62,6 +62,9 @@ const (
|
||||||
configFilename = "config.json"
|
configFilename = "config.json"
|
||||||
defaultRuntime = "runc"
|
defaultRuntime = "runc"
|
||||||
defaultShim = "containerd-shim"
|
defaultShim = "containerd-shim"
|
||||||
|
|
||||||
|
// cleanupTimeout is default timeout for cleanup operations
|
||||||
|
cleanupTimeout = 1 * time.Minute
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -212,7 +215,10 @@ func (r *Runtime) Create(ctx context.Context, id string, opts runtime.CreateOpts
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if kerr := s.KillShim(ctx); kerr != nil {
|
deferCtx, deferCancel := context.WithTimeout(
|
||||||
|
namespaces.WithNamespace(context.TODO(), namespace), cleanupTimeout)
|
||||||
|
defer deferCancel()
|
||||||
|
if kerr := s.KillShim(deferCtx); kerr != nil {
|
||||||
log.G(ctx).WithError(err).Error("failed to kill shim")
|
log.G(ctx).WithError(err).Error("failed to kill shim")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,9 +57,17 @@ func WithStart(binary, address, daemonAddress, cgroup string, debug bool, exitHa
|
||||||
return func(ctx context.Context, config shim.Config) (_ shimapi.ShimService, _ io.Closer, err error) {
|
return func(ctx context.Context, config shim.Config) (_ shimapi.ShimService, _ io.Closer, err error) {
|
||||||
socket, err := newSocket(address)
|
socket, err := newSocket(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if !eaddrinuse(err) {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
defer socket.Close()
|
if err := RemoveSocket(address); err != nil {
|
||||||
|
return nil, nil, errors.Wrap(err, "remove already used socket")
|
||||||
|
}
|
||||||
|
if socket, err = newSocket(address); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
f, err := socket.File()
|
f, err := socket.File()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, errors.Wrapf(err, "failed to get fd for socket %s", address)
|
return nil, nil, errors.Wrapf(err, "failed to get fd for socket %s", address)
|
||||||
|
@ -104,6 +112,8 @@ func WithStart(binary, address, daemonAddress, cgroup string, debug bool, exitHa
|
||||||
if stderrLog != nil {
|
if stderrLog != nil {
|
||||||
stderrLog.Close()
|
stderrLog.Close()
|
||||||
}
|
}
|
||||||
|
socket.Close()
|
||||||
|
RemoveSocket(address)
|
||||||
}()
|
}()
|
||||||
log.G(ctx).WithFields(logrus.Fields{
|
log.G(ctx).WithFields(logrus.Fields{
|
||||||
"pid": cmd.Process.Pid,
|
"pid": cmd.Process.Pid,
|
||||||
|
@ -138,8 +148,29 @@ func WithStart(binary, address, daemonAddress, cgroup string, debug bool, exitHa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func eaddrinuse(err error) bool {
|
||||||
|
cause := errors.Cause(err)
|
||||||
|
netErr, ok := cause.(*net.OpError)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if netErr.Op != "listen" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
syscallErr, ok := netErr.Err.(*os.SyscallError)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
errno, ok := syscallErr.Err.(syscall.Errno)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return errno == syscall.EADDRINUSE
|
||||||
|
}
|
||||||
|
|
||||||
// setupOOMScore gets containerd's oom score and adds +1 to it
|
// setupOOMScore gets containerd's oom score and adds +1 to it
|
||||||
// to ensure a shim has a lower* score than the daemons
|
// to ensure a shim has a lower* score than the daemons
|
||||||
|
// if not already at the maximum OOM Score
|
||||||
func setupOOMScore(shimPid int) error {
|
func setupOOMScore(shimPid int) error {
|
||||||
pid := os.Getpid()
|
pid := os.Getpid()
|
||||||
score, err := sys.GetOOMScoreAdj(pid)
|
score, err := sys.GetOOMScoreAdj(pid)
|
||||||
|
@ -147,6 +178,9 @@ func setupOOMScore(shimPid int) error {
|
||||||
return errors.Wrap(err, "get daemon OOM score")
|
return errors.Wrap(err, "get daemon OOM score")
|
||||||
}
|
}
|
||||||
shimScore := score + 1
|
shimScore := score + 1
|
||||||
|
if shimScore > sys.OOMScoreAdjMax {
|
||||||
|
shimScore = sys.OOMScoreAdjMax
|
||||||
|
}
|
||||||
if err := sys.SetOOMScore(shimPid, shimScore); err != nil {
|
if err := sys.SetOOMScore(shimPid, shimScore); err != nil {
|
||||||
return errors.Wrap(err, "set shim OOM score")
|
return errors.Wrap(err, "set shim OOM score")
|
||||||
}
|
}
|
||||||
|
@ -210,31 +244,73 @@ func writeFile(path, address string) error {
|
||||||
return os.Rename(tempPath, path)
|
return os.Rename(tempPath, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newSocket(address string) (*net.UnixListener, error) {
|
const (
|
||||||
if len(address) > 106 {
|
abstractSocketPrefix = "\x00"
|
||||||
return nil, errors.Errorf("%q: unix socket path too long (> 106)", address)
|
socketPathLimit = 106
|
||||||
|
)
|
||||||
|
|
||||||
|
type socket string
|
||||||
|
|
||||||
|
func (s socket) isAbstract() bool {
|
||||||
|
return !strings.HasPrefix(string(s), "unix://")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s socket) path() string {
|
||||||
|
path := strings.TrimPrefix(string(s), "unix://")
|
||||||
|
// if there was no trim performed, we assume an abstract socket
|
||||||
|
if len(path) == len(s) {
|
||||||
|
path = abstractSocketPrefix + path
|
||||||
}
|
}
|
||||||
l, err := net.Listen("unix", "\x00"+address)
|
return path
|
||||||
|
}
|
||||||
|
|
||||||
|
func newSocket(address string) (*net.UnixListener, error) {
|
||||||
|
if len(address) > socketPathLimit {
|
||||||
|
return nil, errors.Errorf("%q: unix socket path too long (> %d)", address, socketPathLimit)
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
sock = socket(address)
|
||||||
|
path = sock.path()
|
||||||
|
)
|
||||||
|
if !sock.isAbstract() {
|
||||||
|
if err := os.MkdirAll(filepath.Dir(path), 0600); err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "%s", path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
l, err := net.Listen("unix", path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "failed to listen to abstract unix socket %q", address)
|
return nil, errors.Wrapf(err, "failed to listen to unix socket %q (abstract: %t)", address, sock.isAbstract())
|
||||||
|
}
|
||||||
|
if err := os.Chmod(path, 0600); err != nil {
|
||||||
|
l.Close()
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return l.(*net.UnixListener), nil
|
return l.(*net.UnixListener), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RemoveSocket removes the socket at the specified address if
|
||||||
|
// it exists on the filesystem
|
||||||
|
func RemoveSocket(address string) error {
|
||||||
|
sock := socket(address)
|
||||||
|
if !sock.isAbstract() {
|
||||||
|
return os.Remove(sock.path())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func connect(address string, d func(string, time.Duration) (net.Conn, error)) (net.Conn, error) {
|
func connect(address string, d func(string, time.Duration) (net.Conn, error)) (net.Conn, error) {
|
||||||
return d(address, 100*time.Second)
|
return d(address, 100*time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
func annonDialer(address string, timeout time.Duration) (net.Conn, error) {
|
func anonDialer(address string, timeout time.Duration) (net.Conn, error) {
|
||||||
address = strings.TrimPrefix(address, "unix://")
|
return net.DialTimeout("unix", socket(address).path(), timeout)
|
||||||
return net.DialTimeout("unix", "\x00"+address, timeout)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithConnect connects to an existing shim
|
// WithConnect connects to an existing shim
|
||||||
func WithConnect(address string, onClose func()) Opt {
|
func WithConnect(address string, onClose func()) Opt {
|
||||||
return func(ctx context.Context, config shim.Config) (shimapi.ShimService, io.Closer, error) {
|
return func(ctx context.Context, config shim.Config) (shimapi.ShimService, io.Closer, error) {
|
||||||
conn, err := connect(address, annonDialer)
|
conn, err := connect(address, anonDialer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
@ -323,21 +399,31 @@ func (c *Client) signalShim(ctx context.Context, sig syscall.Signal) error {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return ctx.Err()
|
return ctx.Err()
|
||||||
case <-c.waitForExit(pid):
|
case <-c.waitForExit(ctx, pid):
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) waitForExit(pid int) <-chan struct{} {
|
func (c *Client) waitForExit(ctx context.Context, pid int) <-chan struct{} {
|
||||||
c.exitOnce.Do(func() {
|
go c.exitOnce.Do(func() {
|
||||||
|
defer close(c.exitCh)
|
||||||
|
|
||||||
|
ticker := time.NewTicker(10 * time.Millisecond)
|
||||||
|
defer ticker.Stop()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
// use kill(pid, 0) here because the shim could have been reparented
|
// use kill(pid, 0) here because the shim could have been reparented
|
||||||
// and we are no longer able to waitpid(pid, ...) on the shim
|
// and we are no longer able to waitpid(pid, ...) on the shim
|
||||||
if err := unix.Kill(pid, 0); err == unix.ESRCH {
|
if err := unix.Kill(pid, 0); err == unix.ESRCH {
|
||||||
close(c.exitCh)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
time.Sleep(10 * time.Millisecond)
|
|
||||||
|
select {
|
||||||
|
case <-ticker.C:
|
||||||
|
case <-ctx.Done():
|
||||||
|
log.G(ctx).WithField("pid", pid).Warn("timed out while waiting for shim to exit")
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return c.exitCh
|
return c.exitCh
|
||||||
|
|
|
@ -26,6 +26,7 @@ import (
|
||||||
|
|
||||||
"github.com/containerd/containerd/events/exchange"
|
"github.com/containerd/containerd/events/exchange"
|
||||||
"github.com/containerd/containerd/log"
|
"github.com/containerd/containerd/log"
|
||||||
|
"github.com/containerd/containerd/namespaces"
|
||||||
"github.com/containerd/containerd/runtime"
|
"github.com/containerd/containerd/runtime"
|
||||||
client "github.com/containerd/containerd/runtime/v2/shim"
|
client "github.com/containerd/containerd/runtime/v2/shim"
|
||||||
"github.com/containerd/containerd/runtime/v2/task"
|
"github.com/containerd/containerd/runtime/v2/task"
|
||||||
|
@ -74,7 +75,15 @@ func (b *binary) Start(ctx context.Context, opts *types.Any, onClose func()) (_
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
f, err := openShimLog(ctx, b.bundle, client.AnonDialer)
|
// Windows needs a namespace when openShimLog
|
||||||
|
ns, _ := namespaces.Namespace(ctx)
|
||||||
|
shimCtx, cancelShimLog := context.WithCancel(namespaces.WithNamespace(context.Background(), ns))
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
cancelShimLog()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
f, err := openShimLog(shimCtx, b.bundle, client.AnonDialer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "open shim log pipe")
|
return nil, errors.Wrap(err, "open shim log pipe")
|
||||||
}
|
}
|
||||||
|
@ -103,7 +112,11 @@ func (b *binary) Start(ctx context.Context, opts *types.Any, onClose func()) (_
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
client := ttrpc.NewClient(conn, ttrpc.WithOnClose(onClose))
|
onCloseWithShimLog := func() {
|
||||||
|
onClose()
|
||||||
|
cancelShimLog()
|
||||||
|
}
|
||||||
|
client := ttrpc.NewClient(conn, ttrpc.WithOnClose(onCloseWithShimLog))
|
||||||
return &shim{
|
return &shim{
|
||||||
bundle: b.bundle,
|
bundle: b.bundle,
|
||||||
client: client,
|
client: client,
|
||||||
|
|
|
@ -29,6 +29,7 @@ import (
|
||||||
"github.com/containerd/containerd/metadata"
|
"github.com/containerd/containerd/metadata"
|
||||||
"github.com/containerd/containerd/mount"
|
"github.com/containerd/containerd/mount"
|
||||||
"github.com/containerd/containerd/namespaces"
|
"github.com/containerd/containerd/namespaces"
|
||||||
|
"github.com/containerd/containerd/pkg/timeout"
|
||||||
"github.com/containerd/containerd/platforms"
|
"github.com/containerd/containerd/platforms"
|
||||||
"github.com/containerd/containerd/plugin"
|
"github.com/containerd/containerd/plugin"
|
||||||
"github.com/containerd/containerd/runtime"
|
"github.com/containerd/containerd/runtime"
|
||||||
|
@ -154,9 +155,14 @@ func (m *TaskManager) Create(ctx context.Context, id string, opts runtime.Create
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
shim.Shutdown(ctx)
|
dctx, cancel := timeout.WithContext(context.Background(), cleanupTimeout)
|
||||||
|
defer cancel()
|
||||||
|
_, errShim := shim.Delete(dctx)
|
||||||
|
if errShim != nil {
|
||||||
|
shim.Shutdown(dctx)
|
||||||
shim.Close()
|
shim.Close()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}()
|
}()
|
||||||
t, err := shim.Create(ctx, opts)
|
t, err := shim.Create(ctx, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -20,6 +20,7 @@ package runc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -87,6 +88,10 @@ func NewContainer(ctx context.Context, platform stdio.Platform, r *task.CreateTa
|
||||||
Options: r.Options,
|
Options: r.Options,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := WriteOptions(r.Bundle, opts); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// For historical reason, we write opts.BinaryName as well as the entire opts
|
||||||
if err := WriteRuntime(r.Bundle, opts.BinaryName); err != nil {
|
if err := WriteRuntime(r.Bundle, opts.BinaryName); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -142,6 +147,39 @@ func NewContainer(ctx context.Context, platform stdio.Platform, r *task.CreateTa
|
||||||
return container, nil
|
return container, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const optionsFilename = "options.json"
|
||||||
|
|
||||||
|
// ReadOptions reads the option information from the path.
|
||||||
|
// When the file does not exist, ReadOptions returns nil without an error.
|
||||||
|
func ReadOptions(path string) (*options.Options, error) {
|
||||||
|
filePath := filepath.Join(path, optionsFilename)
|
||||||
|
if _, err := os.Stat(filePath); err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := ioutil.ReadFile(filePath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var opts options.Options
|
||||||
|
if err := json.Unmarshal(data, &opts); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &opts, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteOptions writes the options information into the path
|
||||||
|
func WriteOptions(path string, opts options.Options) error {
|
||||||
|
data, err := json.Marshal(opts)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return ioutil.WriteFile(filepath.Join(path, optionsFilename), data, 0600)
|
||||||
|
}
|
||||||
|
|
||||||
// ReadRuntime reads the runtime information from the path
|
// ReadRuntime reads the runtime information from the path
|
||||||
func ReadRuntime(path string) (string, error) {
|
func ReadRuntime(path string) (string, error) {
|
||||||
data, err := ioutil.ReadFile(filepath.Join(path, "runtime"))
|
data, err := ioutil.ReadFile(filepath.Join(path, "runtime"))
|
||||||
|
|
|
@ -25,7 +25,6 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
|
||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
@ -96,6 +95,10 @@ func New(ctx context.Context, id string, publisher shim.Publisher, shutdown func
|
||||||
return nil, errors.Wrap(err, "failed to initialized platform behavior")
|
return nil, errors.Wrap(err, "failed to initialized platform behavior")
|
||||||
}
|
}
|
||||||
go s.forward(ctx, publisher)
|
go s.forward(ctx, publisher)
|
||||||
|
|
||||||
|
if address, err := shim.ReadAddress("address"); err == nil {
|
||||||
|
s.shimAddress = address
|
||||||
|
}
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,6 +118,7 @@ type service struct {
|
||||||
|
|
||||||
containers map[string]*runc.Container
|
containers map[string]*runc.Container
|
||||||
|
|
||||||
|
shimAddress string
|
||||||
cancel func()
|
cancel func()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,7 +162,7 @@ func readSpec() (*spec, error) {
|
||||||
return &s, nil
|
return &s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) StartShim(ctx context.Context, id, containerdBinary, containerdAddress, containerdTTRPCAddress string) (string, error) {
|
func (s *service) StartShim(ctx context.Context, id, containerdBinary, containerdAddress, containerdTTRPCAddress string) (_ string, retErr error) {
|
||||||
cmd, err := newCommand(ctx, id, containerdBinary, containerdAddress, containerdTTRPCAddress)
|
cmd, err := newCommand(ctx, id, containerdBinary, containerdAddress, containerdTTRPCAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
@ -174,34 +178,52 @@ func (s *service) StartShim(ctx context.Context, id, containerdBinary, container
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
address, err := shim.SocketAddress(ctx, grouping)
|
address, err := shim.SocketAddress(ctx, containerdAddress, grouping)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
socket, err := shim.NewSocket(address)
|
socket, err := shim.NewSocket(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if strings.Contains(err.Error(), "address already in use") {
|
// the only time where this would happen is if there is a bug and the socket
|
||||||
|
// was not cleaned up in the cleanup method of the shim or we are using the
|
||||||
|
// grouping functionality where the new process should be run with the same
|
||||||
|
// shim as an existing container
|
||||||
|
if !shim.SocketEaddrinuse(err) {
|
||||||
|
return "", errors.Wrap(err, "create new shim socket")
|
||||||
|
}
|
||||||
|
if shim.CanConnect(address) {
|
||||||
if err := shim.WriteAddress("address", address); err != nil {
|
if err := shim.WriteAddress("address", address); err != nil {
|
||||||
return "", err
|
return "", errors.Wrap(err, "write existing socket for shim")
|
||||||
}
|
}
|
||||||
return address, nil
|
return address, nil
|
||||||
}
|
}
|
||||||
return "", err
|
if err := shim.RemoveSocket(address); err != nil {
|
||||||
|
return "", errors.Wrap(err, "remove pre-existing socket")
|
||||||
}
|
}
|
||||||
defer socket.Close()
|
if socket, err = shim.NewSocket(address); err != nil {
|
||||||
|
return "", errors.Wrap(err, "try create new shim socket 2x")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if retErr != nil {
|
||||||
|
socket.Close()
|
||||||
|
_ = shim.RemoveSocket(address)
|
||||||
|
}
|
||||||
|
}()
|
||||||
f, err := socket.File()
|
f, err := socket.File()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
cmd.ExtraFiles = append(cmd.ExtraFiles, f)
|
cmd.ExtraFiles = append(cmd.ExtraFiles, f)
|
||||||
|
|
||||||
if err := cmd.Start(); err != nil {
|
if err := cmd.Start(); err != nil {
|
||||||
|
f.Close()
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
if retErr != nil {
|
||||||
cmd.Process.Kill()
|
cmd.Process.Kill()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
@ -251,12 +273,20 @@ func (s *service) Cleanup(ctx context.Context) (*taskAPI.DeleteResponse, error)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
runtime, err := runc.ReadRuntime(path)
|
runtime, err := runc.ReadRuntime(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
r := process.NewRunc(process.RuncRoot, path, ns, runtime, "", false)
|
opts, err := runc.ReadOptions(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
root := process.RuncRoot
|
||||||
|
if opts != nil && opts.Root != "" {
|
||||||
|
root = opts.Root
|
||||||
|
}
|
||||||
|
|
||||||
|
r := process.NewRunc(root, path, ns, runtime, "", false)
|
||||||
if err := r.Delete(ctx, s.id, &runcC.DeleteOpts{
|
if err := r.Delete(ctx, s.id, &runcC.DeleteOpts{
|
||||||
Force: true,
|
Force: true,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
|
@ -316,11 +346,12 @@ func (s *service) Start(ctx context.Context, r *taskAPI.StartRequest) (*taskAPI.
|
||||||
s.eventSendMu.Unlock()
|
s.eventSendMu.Unlock()
|
||||||
return nil, errdefs.ToGRPC(err)
|
return nil, errdefs.ToGRPC(err)
|
||||||
}
|
}
|
||||||
|
switch r.ExecID {
|
||||||
|
case "":
|
||||||
if err := s.ep.Add(container.ID, container.Cgroup()); err != nil {
|
if err := s.ep.Add(container.ID, container.Cgroup()); err != nil {
|
||||||
logrus.WithError(err).Error("add cg to OOM monitor")
|
logrus.WithError(err).Error("add cg to OOM monitor")
|
||||||
}
|
}
|
||||||
switch r.ExecID {
|
|
||||||
case "":
|
|
||||||
s.send(&eventstypes.TaskStart{
|
s.send(&eventstypes.TaskStart{
|
||||||
ContainerID: container.ID,
|
ContainerID: container.ID,
|
||||||
Pid: uint32(p.Pid()),
|
Pid: uint32(p.Pid()),
|
||||||
|
@ -348,15 +379,11 @@ func (s *service) Delete(ctx context.Context, r *taskAPI.DeleteRequest) (*taskAP
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errdefs.ToGRPC(err)
|
return nil, errdefs.ToGRPC(err)
|
||||||
}
|
}
|
||||||
// if we deleted our init task, close the platform and send the task delete event
|
// if we deleted an init task, send the task delete event
|
||||||
if r.ExecID == "" {
|
if r.ExecID == "" {
|
||||||
s.mu.Lock()
|
s.mu.Lock()
|
||||||
delete(s.containers, r.ID)
|
delete(s.containers, r.ID)
|
||||||
hasContainers := len(s.containers) > 0
|
|
||||||
s.mu.Unlock()
|
s.mu.Unlock()
|
||||||
if s.platform != nil && !hasContainers {
|
|
||||||
s.platform.Close()
|
|
||||||
}
|
|
||||||
s.send(&eventstypes.TaskDelete{
|
s.send(&eventstypes.TaskDelete{
|
||||||
ContainerID: container.ID,
|
ContainerID: container.ID,
|
||||||
Pid: uint32(p.Pid()),
|
Pid: uint32(p.Pid()),
|
||||||
|
@ -593,13 +620,21 @@ func (s *service) Connect(ctx context.Context, r *taskAPI.ConnectRequest) (*task
|
||||||
|
|
||||||
func (s *service) Shutdown(ctx context.Context, r *taskAPI.ShutdownRequest) (*ptypes.Empty, error) {
|
func (s *service) Shutdown(ctx context.Context, r *taskAPI.ShutdownRequest) (*ptypes.Empty, error) {
|
||||||
s.mu.Lock()
|
s.mu.Lock()
|
||||||
|
defer s.mu.Unlock()
|
||||||
|
|
||||||
// return out if the shim is still servicing containers
|
// return out if the shim is still servicing containers
|
||||||
if len(s.containers) > 0 {
|
if len(s.containers) > 0 {
|
||||||
s.mu.Unlock()
|
|
||||||
return empty, nil
|
return empty, nil
|
||||||
}
|
}
|
||||||
s.cancel()
|
s.cancel()
|
||||||
close(s.events)
|
close(s.events)
|
||||||
|
|
||||||
|
if s.platform != nil {
|
||||||
|
s.platform.Close()
|
||||||
|
}
|
||||||
|
if s.shimAddress != "" {
|
||||||
|
_ = shim.RemoveSocket(s.shimAddress)
|
||||||
|
}
|
||||||
return empty, nil
|
return empty, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -727,9 +762,7 @@ func (s *service) forward(ctx context.Context, publisher shim.Publisher) {
|
||||||
ns, _ := namespaces.Namespace(ctx)
|
ns, _ := namespaces.Namespace(ctx)
|
||||||
ctx = namespaces.WithNamespace(context.Background(), ns)
|
ctx = namespaces.WithNamespace(context.Background(), ns)
|
||||||
for e := range s.events {
|
for e := range s.events {
|
||||||
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
|
||||||
err := publisher.Publish(ctx, runc.GetTopic(e), e)
|
err := publisher.Publish(ctx, runc.GetTopic(e), e)
|
||||||
cancel()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.WithError(err).Error("post event")
|
logrus.WithError(err).Error("post event")
|
||||||
}
|
}
|
||||||
|
|
|
@ -235,11 +235,11 @@ func (s *shim) Delete(ctx context.Context) (*runtime.Exit, error) {
|
||||||
// this seems dirty but it cleans up the API across runtimes, tasks, and the service
|
// this seems dirty but it cleans up the API across runtimes, tasks, and the service
|
||||||
s.rtTasks.Delete(ctx, s.ID())
|
s.rtTasks.Delete(ctx, s.ID())
|
||||||
if err := s.waitShutdown(ctx); err != nil {
|
if err := s.waitShutdown(ctx); err != nil {
|
||||||
log.G(ctx).WithError(err).Error("failed to shutdown shim")
|
log.G(ctx).WithField("id", s.ID()).WithError(err).Error("failed to shutdown shim")
|
||||||
}
|
}
|
||||||
s.Close()
|
s.Close()
|
||||||
if err := s.bundle.Delete(); err != nil {
|
if err := s.bundle.Delete(); err != nil {
|
||||||
log.G(ctx).WithError(err).Error("failed to delete bundle")
|
log.G(ctx).WithField("id", s.ID()).WithError(err).Error("failed to delete bundle")
|
||||||
}
|
}
|
||||||
if shimErr != nil {
|
if shimErr != nil {
|
||||||
return nil, shimErr
|
return nil, shimErr
|
||||||
|
@ -430,10 +430,14 @@ func (s *shim) Stats(ctx context.Context) (*ptypes.Any, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *shim) Process(ctx context.Context, id string) (runtime.Process, error) {
|
func (s *shim) Process(ctx context.Context, id string) (runtime.Process, error) {
|
||||||
return &process{
|
p := &process{
|
||||||
id: id,
|
id: id,
|
||||||
shim: s,
|
shim: s,
|
||||||
}, nil
|
}
|
||||||
|
if _, err := p.State(ctx); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return p, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *shim) State(ctx context.Context) (runtime.State, error) {
|
func (s *shim) State(ctx context.Context) (runtime.State, error) {
|
||||||
|
|
|
@ -128,7 +128,9 @@ func (l *RemoteEventsPublisher) Publish(ctx context.Context, topic string, event
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *RemoteEventsPublisher) forwardRequest(ctx context.Context, req *v1.ForwardRequest) error {
|
func (l *RemoteEventsPublisher) forwardRequest(ctx context.Context, req *v1.ForwardRequest) error {
|
||||||
_, err := l.client.EventsService().Forward(ctx, req)
|
fCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
||||||
|
_, err := l.client.EventsService().Forward(fCtx, req)
|
||||||
|
cancel()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -142,9 +144,9 @@ func (l *RemoteEventsPublisher) forwardRequest(ctx context.Context, req *v1.Forw
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := l.client.EventsService().Forward(ctx, req); err != nil {
|
fCtx, cancel = context.WithTimeout(ctx, 5*time.Second)
|
||||||
return err
|
_, err = l.client.EventsService().Forward(fCtx, req)
|
||||||
}
|
cancel()
|
||||||
|
|
||||||
return nil
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,7 +101,7 @@ func parseFlags() {
|
||||||
flag.BoolVar(&debugFlag, "debug", false, "enable debug output in logs")
|
flag.BoolVar(&debugFlag, "debug", false, "enable debug output in logs")
|
||||||
flag.StringVar(&namespaceFlag, "namespace", "", "namespace that owns the shim")
|
flag.StringVar(&namespaceFlag, "namespace", "", "namespace that owns the shim")
|
||||||
flag.StringVar(&idFlag, "id", "", "id of the task")
|
flag.StringVar(&idFlag, "id", "", "id of the task")
|
||||||
flag.StringVar(&socketFlag, "socket", "", "abstract socket path to serve")
|
flag.StringVar(&socketFlag, "socket", "", "socket path to serve")
|
||||||
flag.StringVar(&bundlePath, "bundle", "", "path to the bundle if not workdir")
|
flag.StringVar(&bundlePath, "bundle", "", "path to the bundle if not workdir")
|
||||||
|
|
||||||
flag.StringVar(&addressFlag, "address", "", "grpc address back to main containerd")
|
flag.StringVar(&addressFlag, "address", "", "grpc address back to main containerd")
|
||||||
|
@ -183,7 +183,6 @@ func run(id string, initFunc Init, config Config) error {
|
||||||
ctx = context.WithValue(ctx, OptsKey{}, Opts{BundlePath: bundlePath, Debug: debugFlag})
|
ctx = context.WithValue(ctx, OptsKey{}, Opts{BundlePath: bundlePath, Debug: debugFlag})
|
||||||
ctx = log.WithLogger(ctx, log.G(ctx).WithField("runtime", id))
|
ctx = log.WithLogger(ctx, log.G(ctx).WithField("runtime", id))
|
||||||
ctx, cancel := context.WithCancel(ctx)
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
|
|
||||||
service, err := initFunc(ctx, idFlag, publisher, cancel)
|
service, err := initFunc(ctx, idFlag, publisher, cancel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -288,11 +287,15 @@ func serve(ctx context.Context, server *ttrpc.Server, path string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
defer l.Close()
|
|
||||||
if err := server.Serve(ctx, l); err != nil &&
|
if err := server.Serve(ctx, l); err != nil &&
|
||||||
!strings.Contains(err.Error(), "use of closed network connection") {
|
!strings.Contains(err.Error(), "use of closed network connection") {
|
||||||
logrus.WithError(err).Fatal("containerd-shim: ttrpc server failure")
|
logrus.WithError(err).Fatal("containerd-shim: ttrpc server failure")
|
||||||
}
|
}
|
||||||
|
l.Close()
|
||||||
|
if address, err := ReadAddress("address"); err == nil {
|
||||||
|
_ = RemoveSocket(address)
|
||||||
|
}
|
||||||
|
|
||||||
}()
|
}()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,15 +58,15 @@ func serveListener(path string) (net.Listener, error) {
|
||||||
l, err = net.FileListener(os.NewFile(3, "socket"))
|
l, err = net.FileListener(os.NewFile(3, "socket"))
|
||||||
path = "[inherited from parent]"
|
path = "[inherited from parent]"
|
||||||
} else {
|
} else {
|
||||||
if len(path) > 106 {
|
if len(path) > socketPathLimit {
|
||||||
return nil, errors.Errorf("%q: unix socket path too long (> 106)", path)
|
return nil, errors.Errorf("%q: unix socket path too long (> %d)", path, socketPathLimit)
|
||||||
}
|
}
|
||||||
l, err = net.Listen("unix", "\x00"+path)
|
l, err = net.Listen("unix", path)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
logrus.WithField("socket", path).Debug("serving api on abstract socket")
|
logrus.WithField("socket", path).Debug("serving api on socket")
|
||||||
return l, nil
|
return l, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -169,7 +169,7 @@ func WriteAddress(path, address string) error {
|
||||||
// ErrNoAddress is returned when the address file has no content
|
// ErrNoAddress is returned when the address file has no content
|
||||||
var ErrNoAddress = errors.New("no shim address")
|
var ErrNoAddress = errors.New("no shim address")
|
||||||
|
|
||||||
// ReadAddress returns the shim's abstract socket address from the path
|
// ReadAddress returns the shim's socket address from the path
|
||||||
func ReadAddress(path string) (string, error) {
|
func ReadAddress(path string) (string, error) {
|
||||||
path, err := filepath.Abs(path)
|
path, err := filepath.Abs(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -34,7 +34,10 @@ import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
const shimBinaryFormat = "containerd-shim-%s-%s"
|
const (
|
||||||
|
shimBinaryFormat = "containerd-shim-%s-%s"
|
||||||
|
socketPathLimit = 106
|
||||||
|
)
|
||||||
|
|
||||||
func getSysProcAttr() *syscall.SysProcAttr {
|
func getSysProcAttr() *syscall.SysProcAttr {
|
||||||
return &syscall.SysProcAttr{
|
return &syscall.SysProcAttr{
|
||||||
|
@ -49,6 +52,7 @@ func SetScore(pid int) error {
|
||||||
|
|
||||||
// AdjustOOMScore sets the OOM score for the process to the parents OOM score +1
|
// AdjustOOMScore sets the OOM score for the process to the parents OOM score +1
|
||||||
// to ensure that they parent has a lower* score than the shim
|
// to ensure that they parent has a lower* score than the shim
|
||||||
|
// if not already at the maximum OOM Score
|
||||||
func AdjustOOMScore(pid int) error {
|
func AdjustOOMScore(pid int) error {
|
||||||
parent := os.Getppid()
|
parent := os.Getppid()
|
||||||
score, err := sys.GetOOMScoreAdj(parent)
|
score, err := sys.GetOOMScoreAdj(parent)
|
||||||
|
@ -56,26 +60,30 @@ func AdjustOOMScore(pid int) error {
|
||||||
return errors.Wrap(err, "get parent OOM score")
|
return errors.Wrap(err, "get parent OOM score")
|
||||||
}
|
}
|
||||||
shimScore := score + 1
|
shimScore := score + 1
|
||||||
|
if shimScore > sys.OOMScoreAdjMax {
|
||||||
|
shimScore = sys.OOMScoreAdjMax
|
||||||
|
}
|
||||||
if err := sys.SetOOMScore(pid, shimScore); err != nil {
|
if err := sys.SetOOMScore(pid, shimScore); err != nil {
|
||||||
return errors.Wrap(err, "set shim OOM score")
|
return errors.Wrap(err, "set shim OOM score")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SocketAddress returns an abstract socket address
|
const socketRoot = "/run/containerd"
|
||||||
func SocketAddress(ctx context.Context, id string) (string, error) {
|
|
||||||
|
// SocketAddress returns a socket address
|
||||||
|
func SocketAddress(ctx context.Context, socketPath, id string) (string, error) {
|
||||||
ns, err := namespaces.NamespaceRequired(ctx)
|
ns, err := namespaces.NamespaceRequired(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
d := sha256.Sum256([]byte(filepath.Join(ns, id)))
|
d := sha256.Sum256([]byte(filepath.Join(socketPath, ns, id)))
|
||||||
return filepath.Join(string(filepath.Separator), "containerd-shim", fmt.Sprintf("%x.sock", d)), nil
|
return fmt.Sprintf("unix://%s/%x", filepath.Join(socketRoot, "s"), d), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AnonDialer returns a dialer for an abstract socket
|
// AnonDialer returns a dialer for a socket
|
||||||
func AnonDialer(address string, timeout time.Duration) (net.Conn, error) {
|
func AnonDialer(address string, timeout time.Duration) (net.Conn, error) {
|
||||||
address = strings.TrimPrefix(address, "unix://")
|
return net.DialTimeout("unix", socket(address).path(), timeout)
|
||||||
return net.DialTimeout("unix", "\x00"+address, timeout)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func AnonReconnectDialer(address string, timeout time.Duration) (net.Conn, error) {
|
func AnonReconnectDialer(address string, timeout time.Duration) (net.Conn, error) {
|
||||||
|
@ -84,12 +92,82 @@ func AnonReconnectDialer(address string, timeout time.Duration) (net.Conn, error
|
||||||
|
|
||||||
// NewSocket returns a new socket
|
// NewSocket returns a new socket
|
||||||
func NewSocket(address string) (*net.UnixListener, error) {
|
func NewSocket(address string) (*net.UnixListener, error) {
|
||||||
if len(address) > 106 {
|
var (
|
||||||
return nil, errors.Errorf("%q: unix socket path too long (> 106)", address)
|
sock = socket(address)
|
||||||
|
path = sock.path()
|
||||||
|
)
|
||||||
|
if !sock.isAbstract() {
|
||||||
|
if err := os.MkdirAll(filepath.Dir(path), 0600); err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "%s", path)
|
||||||
}
|
}
|
||||||
l, err := net.Listen("unix", "\x00"+address)
|
}
|
||||||
|
l, err := net.Listen("unix", path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "failed to listen to abstract unix socket %q", address)
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := os.Chmod(path, 0600); err != nil {
|
||||||
|
os.Remove(sock.path())
|
||||||
|
l.Close()
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
return l.(*net.UnixListener), nil
|
return l.(*net.UnixListener), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const abstractSocketPrefix = "\x00"
|
||||||
|
|
||||||
|
type socket string
|
||||||
|
|
||||||
|
func (s socket) isAbstract() bool {
|
||||||
|
return !strings.HasPrefix(string(s), "unix://")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s socket) path() string {
|
||||||
|
path := strings.TrimPrefix(string(s), "unix://")
|
||||||
|
// if there was no trim performed, we assume an abstract socket
|
||||||
|
if len(path) == len(s) {
|
||||||
|
path = abstractSocketPrefix + path
|
||||||
|
}
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveSocket removes the socket at the specified address if
|
||||||
|
// it exists on the filesystem
|
||||||
|
func RemoveSocket(address string) error {
|
||||||
|
sock := socket(address)
|
||||||
|
if !sock.isAbstract() {
|
||||||
|
return os.Remove(sock.path())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SocketEaddrinuse returns true if the provided error is caused by the
|
||||||
|
// EADDRINUSE error number
|
||||||
|
func SocketEaddrinuse(err error) bool {
|
||||||
|
netErr, ok := err.(*net.OpError)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if netErr.Op != "listen" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
syscallErr, ok := netErr.Err.(*os.SyscallError)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
errno, ok := syscallErr.Err.(syscall.Errno)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return errno == syscall.EADDRINUSE
|
||||||
|
}
|
||||||
|
|
||||||
|
// CanConnect returns true if the socket provided at the address
|
||||||
|
// is accepting new connections
|
||||||
|
func CanConnect(address string) bool {
|
||||||
|
conn, err := AnonDialer(address, 100*time.Millisecond)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
conn.Close()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
|
@ -79,3 +79,9 @@ func AnonDialer(address string, timeout time.Duration) (net.Conn, error) {
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RemoveSocket removes the socket at the specified address if
|
||||||
|
// it exists on the filesystem
|
||||||
|
func RemoveSocket(address string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -115,7 +115,7 @@ func (s *service) List(req *api.ListContentRequest, session api.Content_ListServ
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}, req.Filters...); err != nil {
|
}, req.Filters...); err != nil {
|
||||||
return err
|
return errdefs.ToGRPC(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(buffer) > 0 {
|
if len(buffer) > 0 {
|
||||||
|
|
|
@ -20,7 +20,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
|
||||||
|
|
||||||
"github.com/containerd/containerd/plugin"
|
"github.com/containerd/containerd/plugin"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
@ -42,23 +41,21 @@ func init() {
|
||||||
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
|
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
|
||||||
path := ic.Config.(*Config).Path
|
path := ic.Config.(*Config).Path
|
||||||
ic.Meta.Exports["path"] = path
|
ic.Meta.Exports["path"] = path
|
||||||
|
|
||||||
bin := filepath.Join(path, "bin")
|
bin := filepath.Join(path, "bin")
|
||||||
if err := os.MkdirAll(bin, 0711); err != nil {
|
if err := os.MkdirAll(bin, 0711); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := os.Setenv("PATH", fmt.Sprintf("%s:%s", bin, os.Getenv("PATH"))); err != nil {
|
if err := os.Setenv("PATH", fmt.Sprintf("%s%c%s", bin, os.PathListSeparator, os.Getenv("PATH"))); err != nil {
|
||||||
return nil, errors.Wrapf(err, "set binary image directory in path %s", bin)
|
return nil, errors.Wrapf(err, "set binary image directory in path %s", bin)
|
||||||
}
|
}
|
||||||
if runtime.GOOS != "windows" {
|
|
||||||
lib := filepath.Join(path, "lib")
|
lib := filepath.Join(path, "lib")
|
||||||
if err := os.MkdirAll(lib, 0711); err != nil {
|
if err := os.MkdirAll(lib, 0711); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := os.Setenv("LD_LIBRARY_PATH", fmt.Sprintf("%s:%s", os.Getenv("LD_LIBRARY_PATH"), lib)); err != nil {
|
if err := os.Setenv("LD_LIBRARY_PATH", fmt.Sprintf("%s%c%s", lib, os.PathListSeparator, os.Getenv("LD_LIBRARY_PATH"))); err != nil {
|
||||||
return nil, errors.Wrapf(err, "set binary lib directory in path %s", lib)
|
return nil, errors.Wrapf(err, "set binary lib directory in path %s", lib)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return &manager{}, nil
|
return &manager{}, nil
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
|
@ -118,6 +118,13 @@ func initFunc(ic *plugin.InitContext) (interface{}, error) {
|
||||||
l.monitor.Monitor(t)
|
l.monitor.Monitor(t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
v2Tasks, err := l.v2Runtime.Tasks(ic.Context, true)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, t := range v2Tasks {
|
||||||
|
l.monitor.Monitor(t)
|
||||||
|
}
|
||||||
return l, nil
|
return l, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -297,7 +297,7 @@ func Remove(ctx context.Context, key string) (string, snapshots.Kind, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := readSnapshot(sbkt, &id, &si); err != nil {
|
if err := readSnapshot(sbkt, &id, &si); err != nil {
|
||||||
errors.Wrapf(err, "failed to read snapshot %s", key)
|
return errors.Wrapf(err, "failed to read snapshot %s", key)
|
||||||
}
|
}
|
||||||
|
|
||||||
if pbkt != nil {
|
if pbkt != nil {
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package sys
|
||||||
|
|
||||||
|
import "os"
|
||||||
|
|
||||||
|
// IsFifo checks if a file is a (named pipe) fifo
|
||||||
|
// if the file does not exist then it returns false
|
||||||
|
func IsFifo(path string) (bool, error) {
|
||||||
|
stat, err := os.Stat(path)
|
||||||
|
if err != nil {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if stat.Mode()&os.ModeNamedPipe == os.ModeNamedPipe {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/log"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
@ -30,9 +31,8 @@ func FMountat(dirfd uintptr, source, target, fstype string, flags uintptr, data
|
||||||
var (
|
var (
|
||||||
sourceP, targetP, fstypeP, dataP *byte
|
sourceP, targetP, fstypeP, dataP *byte
|
||||||
pid uintptr
|
pid uintptr
|
||||||
ws unix.WaitStatus
|
|
||||||
err error
|
err error
|
||||||
errno syscall.Errno
|
errno, status syscall.Errno
|
||||||
)
|
)
|
||||||
|
|
||||||
sourceP, err = syscall.BytePtrFromString(source)
|
sourceP, err = syscall.BytePtrFromString(source)
|
||||||
|
@ -60,37 +60,62 @@ func FMountat(dirfd uintptr, source, target, fstype string, flags uintptr, data
|
||||||
runtime.LockOSThread()
|
runtime.LockOSThread()
|
||||||
defer runtime.UnlockOSThread()
|
defer runtime.UnlockOSThread()
|
||||||
|
|
||||||
|
var pipefds [2]int
|
||||||
|
if err := syscall.Pipe2(pipefds[:], syscall.O_CLOEXEC); err != nil {
|
||||||
|
return errors.Wrap(err, "failed to open pipe")
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
// close both ends of the pipe in a deferred function, since open file
|
||||||
|
// descriptor table is shared with child
|
||||||
|
syscall.Close(pipefds[0])
|
||||||
|
syscall.Close(pipefds[1])
|
||||||
|
}()
|
||||||
|
|
||||||
pid, errno = forkAndMountat(dirfd,
|
pid, errno = forkAndMountat(dirfd,
|
||||||
uintptr(unsafe.Pointer(sourceP)),
|
uintptr(unsafe.Pointer(sourceP)),
|
||||||
uintptr(unsafe.Pointer(targetP)),
|
uintptr(unsafe.Pointer(targetP)),
|
||||||
uintptr(unsafe.Pointer(fstypeP)),
|
uintptr(unsafe.Pointer(fstypeP)),
|
||||||
flags,
|
flags,
|
||||||
uintptr(unsafe.Pointer(dataP)))
|
uintptr(unsafe.Pointer(dataP)),
|
||||||
|
pipefds[1],
|
||||||
|
)
|
||||||
|
|
||||||
if errno != 0 {
|
if errno != 0 {
|
||||||
return errors.Wrap(errno, "failed to fork thread")
|
return errors.Wrap(errno, "failed to fork thread")
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = unix.Wait4(int(pid), &ws, 0, nil)
|
defer func() {
|
||||||
|
_, err := unix.Wait4(int(pid), nil, 0, nil)
|
||||||
for err == syscall.EINTR {
|
for err == syscall.EINTR {
|
||||||
_, err = unix.Wait4(int(pid), &ws, 0, nil)
|
_, err = unix.Wait4(int(pid), nil, 0, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "failed to find pid=%d process", pid)
|
log.L.WithError(err).Debugf("failed to find pid=%d process", pid)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
_, _, errno = syscall.RawSyscall(syscall.SYS_READ,
|
||||||
|
uintptr(pipefds[0]),
|
||||||
|
uintptr(unsafe.Pointer(&status)),
|
||||||
|
unsafe.Sizeof(status))
|
||||||
|
if errno != 0 {
|
||||||
|
return errors.Wrap(errno, "failed to read pipe")
|
||||||
}
|
}
|
||||||
|
|
||||||
errno = syscall.Errno(ws.ExitStatus())
|
if status != 0 {
|
||||||
if errno != 0 {
|
return errors.Wrap(status, "failed to mount")
|
||||||
return errors.Wrap(errno, "failed to mount")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// forkAndMountat will fork thread, change working dir and mount.
|
// forkAndMountat will fork thread, change working dir and mount.
|
||||||
//
|
//
|
||||||
// precondition: the runtime OS thread must be locked.
|
// precondition: the runtime OS thread must be locked.
|
||||||
func forkAndMountat(dirfd uintptr, source, target, fstype, flags, data uintptr) (pid uintptr, errno syscall.Errno) {
|
func forkAndMountat(dirfd uintptr, source, target, fstype, flags, data uintptr, pipefd int) (pid uintptr, errno syscall.Errno) {
|
||||||
|
|
||||||
// block signal during clone
|
// block signal during clone
|
||||||
beforeFork()
|
beforeFork()
|
||||||
|
|
||||||
|
@ -114,6 +139,7 @@ func forkAndMountat(dirfd uintptr, source, target, fstype, flags, data uintptr)
|
||||||
_, _, errno = syscall.RawSyscall6(syscall.SYS_MOUNT, source, target, fstype, flags, data, 0)
|
_, _, errno = syscall.RawSyscall6(syscall.SYS_MOUNT, source, target, fstype, flags, data, 0)
|
||||||
|
|
||||||
childerr:
|
childerr:
|
||||||
|
_, _, errno = syscall.RawSyscall(syscall.SYS_WRITE, uintptr(pipefd), uintptr(unsafe.Pointer(&errno)), unsafe.Sizeof(errno))
|
||||||
syscall.RawSyscall(syscall.SYS_EXIT, uintptr(errno), 0, 0)
|
syscall.RawSyscall(syscall.SYS_EXIT, uintptr(errno), 0, 0)
|
||||||
panic("unreachable")
|
panic("unreachable")
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,8 +28,12 @@ import (
|
||||||
"github.com/opencontainers/runc/libcontainer/system"
|
"github.com/opencontainers/runc/libcontainer/system"
|
||||||
)
|
)
|
||||||
|
|
||||||
// OOMScoreMaxKillable is the maximum score keeping the process killable by the oom killer
|
const (
|
||||||
const OOMScoreMaxKillable = -999
|
// OOMScoreMaxKillable is the maximum score keeping the process killable by the oom killer
|
||||||
|
OOMScoreMaxKillable = -999
|
||||||
|
// OOMScoreAdjMax is from OOM_SCORE_ADJ_MAX https://github.com/torvalds/linux/blob/master/include/uapi/linux/oom.h
|
||||||
|
OOMScoreAdjMax = 1000
|
||||||
|
)
|
||||||
|
|
||||||
// SetOOMScore sets the oom score for the provided pid
|
// SetOOMScore sets the oom score for the provided pid
|
||||||
func SetOOMScore(pid, score int) error {
|
func SetOOMScore(pid, score int) error {
|
||||||
|
|
|
@ -16,6 +16,11 @@
|
||||||
|
|
||||||
package sys
|
package sys
|
||||||
|
|
||||||
|
const (
|
||||||
|
// OOMScoreAdjMax is not implemented on Windows
|
||||||
|
OOMScoreAdjMax = 0
|
||||||
|
)
|
||||||
|
|
||||||
// SetOOMScore sets the oom score for the process
|
// SetOOMScore sets the oom score for the process
|
||||||
//
|
//
|
||||||
// Not implemented on Windows
|
// Not implemented on Windows
|
||||||
|
|
|
@ -186,8 +186,32 @@ func (u *unpacker) unpack(ctx context.Context, config ocispec.Descriptor, layers
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *unpacker) handlerWrapper(uctx context.Context, unpacks *int32) (func(images.Handler) images.Handler, *errgroup.Group) {
|
type errGroup struct {
|
||||||
eg, uctx := errgroup.WithContext(uctx)
|
*errgroup.Group
|
||||||
|
cancel context.CancelFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
func newErrGroup(ctx context.Context) (*errGroup, context.Context) {
|
||||||
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
|
eg, ctx := errgroup.WithContext(ctx)
|
||||||
|
return &errGroup{
|
||||||
|
Group: eg,
|
||||||
|
cancel: cancel,
|
||||||
|
}, ctx
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *errGroup) Cancel() {
|
||||||
|
e.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *errGroup) Wait() error {
|
||||||
|
err := e.Group.Wait()
|
||||||
|
e.cancel()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *unpacker) handlerWrapper(uctx context.Context, unpacks *int32) (func(images.Handler) images.Handler, *errGroup) {
|
||||||
|
eg, uctx := newErrGroup(uctx)
|
||||||
return func(f images.Handler) images.Handler {
|
return func(f images.Handler) images.Handler {
|
||||||
var (
|
var (
|
||||||
lock sync.Mutex
|
lock sync.Mutex
|
||||||
|
@ -234,7 +258,19 @@ func (u *unpacker) handlerWrapper(uctx context.Context, unpacks *int32) (func(im
|
||||||
update := !schema1
|
update := !schema1
|
||||||
lock.Unlock()
|
lock.Unlock()
|
||||||
if update {
|
if update {
|
||||||
u.updateCh <- desc
|
select {
|
||||||
|
case <-uctx.Done():
|
||||||
|
// Do not send update if unpacker is not running.
|
||||||
|
default:
|
||||||
|
select {
|
||||||
|
case u.updateCh <- desc:
|
||||||
|
case <-uctx.Done():
|
||||||
|
// Do not send update if unpacker is not running.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Checking ctx.Done() prevents the case that unpacker
|
||||||
|
// exits unexpectedly, but update continues to be generated,
|
||||||
|
// and eventually fills up updateCh and blocks forever.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return children, nil
|
return children, nil
|
||||||
|
|
|
@ -1,91 +1,93 @@
|
||||||
github.com/containerd/go-runc e029b79d8cda8374981c64eba71f28ec38e5526f
|
github.com/beorn7/perks 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9
|
||||||
github.com/containerd/console 0650fd9eeb50bab4fc99dceb9f2e14cf58f36e7f
|
github.com/BurntSushi/toml v0.3.1
|
||||||
github.com/containerd/cgroups c4b9ac5c7601384c965b9646fc515884e091ebb9
|
|
||||||
github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40
|
|
||||||
github.com/containerd/fifo bda0ff6ed73c67bfb5e62bc9c697f146b7fd7f13
|
|
||||||
github.com/containerd/btrfs af5082808c833de0e79c1e72eea9fea239364877
|
github.com/containerd/btrfs af5082808c833de0e79c1e72eea9fea239364877
|
||||||
github.com/containerd/continuity f2a389ac0a02ce21c09edd7344677a601970f41c
|
github.com/containerd/cgroups 9f1c62dddf4bc7cc72822ebe353bae7006141b1b
|
||||||
|
github.com/containerd/console v1.0.0
|
||||||
|
github.com/containerd/continuity 1d9893e5674b5260c3fc11316d0d5fc0d12ea9e2
|
||||||
|
github.com/containerd/fifo bda0ff6ed73c67bfb5e62bc9c697f146b7fd7f13
|
||||||
|
github.com/containerd/go-runc e029b79d8cda8374981c64eba71f28ec38e5526f
|
||||||
|
github.com/containerd/ttrpc v1.0.0
|
||||||
|
github.com/containerd/typeurl v1.0.0
|
||||||
github.com/coreos/go-systemd 48702e0da86bd25e76cfef347e2adeb434a0d0a6
|
github.com/coreos/go-systemd 48702e0da86bd25e76cfef347e2adeb434a0d0a6
|
||||||
|
github.com/cpuguy83/go-md2man v1.0.10
|
||||||
|
github.com/docker/go-events e31b211e4f1cd09aa76fe4ac244571fab96ae47f
|
||||||
github.com/docker/go-metrics 4ea375f7759c82740c893fc030bc37088d2ec098
|
github.com/docker/go-metrics 4ea375f7759c82740c893fc030bc37088d2ec098
|
||||||
github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9
|
|
||||||
github.com/docker/go-units v0.4.0
|
github.com/docker/go-units v0.4.0
|
||||||
github.com/godbus/dbus c7fdd8b5cd55e87b4e1f4e372cdb1db61dd6c66f
|
github.com/godbus/dbus v3
|
||||||
|
github.com/gogo/googleapis v1.2.0
|
||||||
|
github.com/gogo/protobuf v1.2.1
|
||||||
|
github.com/golang/protobuf v1.2.0
|
||||||
|
github.com/google/go-cmp v0.2.0
|
||||||
|
github.com/google/uuid v1.1.1
|
||||||
|
github.com/grpc-ecosystem/go-grpc-prometheus 6b7015e65d366bf3f19b2b2a000a831940f0f7e0
|
||||||
|
github.com/hashicorp/errwrap v1.0.0
|
||||||
|
github.com/hashicorp/go-multierror v1.0.0
|
||||||
|
github.com/hashicorp/golang-lru v0.5.3
|
||||||
|
github.com/imdario/mergo v0.3.7
|
||||||
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1
|
||||||
|
github.com/matttproud/golang_protobuf_extensions v1.0.1
|
||||||
|
github.com/Microsoft/go-winio v0.4.14
|
||||||
|
github.com/Microsoft/hcsshim 9e921883ac929bbe515b39793ece99ce3a9d7706
|
||||||
|
github.com/opencontainers/go-digest c9281466c8b2f606084ac71339773efd177436e7
|
||||||
|
github.com/opencontainers/image-spec v1.0.1
|
||||||
|
github.com/opencontainers/runc v1.0.0-rc10
|
||||||
|
github.com/opencontainers/runtime-spec 29686dbc5559d93fb1ef402eeda3e35c38d75af4 # v1.0.1-59-g29686db
|
||||||
|
github.com/pkg/errors v0.8.1
|
||||||
github.com/prometheus/client_golang f4fb1b73fb099f396a7f0036bf86aa8def4ed823
|
github.com/prometheus/client_golang f4fb1b73fb099f396a7f0036bf86aa8def4ed823
|
||||||
github.com/prometheus/client_model 99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c
|
github.com/prometheus/client_model 99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c
|
||||||
github.com/prometheus/common 89604d197083d4781071d3c65855d24ecfb0a563
|
github.com/prometheus/common 89604d197083d4781071d3c65855d24ecfb0a563
|
||||||
github.com/prometheus/procfs cb4147076ac75738c9a7d279075a253c0cc5acbd
|
github.com/prometheus/procfs cb4147076ac75738c9a7d279075a253c0cc5acbd
|
||||||
github.com/beorn7/perks 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9
|
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1
|
|
||||||
github.com/gogo/protobuf v1.2.1
|
|
||||||
github.com/gogo/googleapis v1.2.0
|
|
||||||
github.com/golang/protobuf v1.2.0
|
|
||||||
github.com/opencontainers/runtime-spec 29686dbc5559d93fb1ef402eeda3e35c38d75af4 # v1.0.1-59-g29686db
|
|
||||||
github.com/opencontainers/runc d736ef14f0288d6993a1845745d6756cfc9ddd5a # v1.0.0-rc9
|
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1
|
|
||||||
github.com/sirupsen/logrus v1.4.1
|
|
||||||
github.com/urfave/cli v1.22.0
|
|
||||||
golang.org/x/net f3200d17e092c607f615320ecaad13d87ad9a2b3
|
|
||||||
google.golang.org/grpc 6eaf6f47437a6b4e2153a190160ef39a92c7eceb # v1.23.0
|
|
||||||
github.com/pkg/errors v0.8.1
|
|
||||||
github.com/opencontainers/go-digest c9281466c8b2f606084ac71339773efd177436e7
|
|
||||||
golang.org/x/sys 9eafafc0a87e0fd0aeeba439a4573537970c44c7 https://github.com/golang/sys
|
|
||||||
github.com/opencontainers/image-spec v1.0.1
|
|
||||||
golang.org/x/sync 42b317875d0fa942474b76e1b46a6060d720ae6e
|
|
||||||
github.com/BurntSushi/toml v0.3.1
|
|
||||||
github.com/grpc-ecosystem/go-grpc-prometheus 6b7015e65d366bf3f19b2b2a000a831940f0f7e0
|
|
||||||
github.com/Microsoft/go-winio v0.4.14
|
|
||||||
github.com/Microsoft/hcsshim 9e921883ac929bbe515b39793ece99ce3a9d7706
|
|
||||||
google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944
|
|
||||||
golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4
|
|
||||||
github.com/containerd/ttrpc 92c8520ef9f86600c650dd540266a007bf03670f
|
|
||||||
github.com/syndtr/gocapability d98352740cb2c55f81556b63d4a1ec64c5a319c2
|
|
||||||
gotest.tools v2.3.0
|
|
||||||
github.com/google/go-cmp v0.2.0
|
|
||||||
go.etcd.io/bbolt v1.3.3
|
|
||||||
github.com/hashicorp/errwrap v1.0.0
|
|
||||||
github.com/hashicorp/go-multierror v1.0.0
|
|
||||||
github.com/hashicorp/golang-lru v0.5.3
|
|
||||||
go.opencensus.io v0.22.0
|
|
||||||
github.com/imdario/mergo v0.3.7
|
|
||||||
github.com/cpuguy83/go-md2man v1.0.10
|
|
||||||
github.com/russross/blackfriday v1.5.2
|
github.com/russross/blackfriday v1.5.2
|
||||||
|
github.com/sirupsen/logrus v1.4.1
|
||||||
|
github.com/syndtr/gocapability d98352740cb2c55f81556b63d4a1ec64c5a319c2
|
||||||
|
github.com/urfave/cli v1.22.0
|
||||||
|
go.etcd.io/bbolt v1.3.3
|
||||||
|
go.opencensus.io v0.22.0
|
||||||
|
golang.org/x/net f3200d17e092c607f615320ecaad13d87ad9a2b3
|
||||||
|
golang.org/x/sync 42b317875d0fa942474b76e1b46a6060d720ae6e
|
||||||
|
golang.org/x/sys 9eafafc0a87e0fd0aeeba439a4573537970c44c7
|
||||||
|
golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4
|
||||||
|
google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944
|
||||||
|
google.golang.org/grpc v1.23.0
|
||||||
|
gotest.tools v2.3.0
|
||||||
|
|
||||||
# cri dependencies
|
# cri dependencies
|
||||||
github.com/containerd/cri 5d49e7e51b43e36a6b9c4386257c7d08c602237f # release/1.3
|
github.com/containerd/cri v1.3.0-k3s.10 https://github.com/k3s-io/cri.git
|
||||||
github.com/containerd/go-cni 49fbd9b210f3c8ee3b7fd3cd797aabaf364627c1
|
|
||||||
github.com/containernetworking/cni v0.7.1
|
|
||||||
github.com/containernetworking/plugins v0.7.6
|
|
||||||
github.com/davecgh/go-spew v1.1.1
|
github.com/davecgh/go-spew v1.1.1
|
||||||
github.com/docker/distribution 0d3efadf0154c2b8a4e7b6621fff9809655cc580
|
github.com/docker/distribution 0d3efadf0154c2b8a4e7b6621fff9809655cc580
|
||||||
github.com/docker/docker 86f080cff0914e9694068ed78d503701667c4c00
|
github.com/docker/docker 86f080cff0914e9694068ed78d503701667c4c00
|
||||||
github.com/docker/spdystream 449fdfce4d962303d702fec724ef0ad181c92528
|
github.com/docker/spdystream 449fdfce4d962303d702fec724ef0ad181c92528
|
||||||
github.com/emicklei/go-restful v2.9.5
|
github.com/emicklei/go-restful v2.9.5
|
||||||
github.com/google/gofuzz v1.0.0
|
github.com/google/gofuzz v1.0.0
|
||||||
github.com/json-iterator/go v1.1.7
|
github.com/json-iterator/go v1.1.8
|
||||||
github.com/modern-go/reflect2 1.0.1
|
|
||||||
github.com/modern-go/concurrent 1.0.3
|
github.com/modern-go/concurrent 1.0.3
|
||||||
github.com/opencontainers/selinux v1.2.2
|
github.com/modern-go/reflect2 1.0.1
|
||||||
|
github.com/opencontainers/selinux bb88c45a3863dc4c38320d71b890bb30ef9feba4
|
||||||
github.com/seccomp/libseccomp-golang v0.9.1
|
github.com/seccomp/libseccomp-golang v0.9.1
|
||||||
github.com/tchap/go-patricia v2.2.6
|
github.com/tchap/go-patricia v2.2.6
|
||||||
golang.org/x/crypto 5c40567a22f818bd14a1ea7245dad9f8ef0691aa
|
golang.org/x/crypto 69ecbb4d6d5dab05e49161c6e77ea40a030884e1
|
||||||
golang.org/x/oauth2 0f29369cfe4552d0e4bcddc57cc75f4d7e672a33
|
golang.org/x/oauth2 0f29369cfe4552d0e4bcddc57cc75f4d7e672a33
|
||||||
golang.org/x/time 85acf8d2951cb2a3bde7632f9ff273ef0379bcbd
|
golang.org/x/time 9d24e82272b4f38b78bc8cff74fa936d31ccd8ef
|
||||||
gopkg.in/inf.v0 v0.9.0
|
gopkg.in/inf.v0 v0.9.1
|
||||||
gopkg.in/yaml.v2 v2.2.2
|
gopkg.in/yaml.v2 v2.2.8
|
||||||
k8s.io/api kubernetes-1.16.0-rc.2
|
k8s.io/api v0.16.6
|
||||||
k8s.io/apimachinery kubernetes-1.16.0-rc.2
|
k8s.io/apimachinery v0.16.6
|
||||||
k8s.io/apiserver kubernetes-1.16.0-rc.2
|
k8s.io/apiserver v0.16.6
|
||||||
k8s.io/cri-api kubernetes-1.16.0-rc.2
|
k8s.io/client-go v0.16.6
|
||||||
k8s.io/client-go kubernetes-1.16.0-rc.2
|
k8s.io/cri-api v0.16.6
|
||||||
k8s.io/klog v0.4.0
|
k8s.io/klog v1.0.0
|
||||||
k8s.io/kubernetes v1.16.0-rc.2
|
k8s.io/kubernetes v1.16.6
|
||||||
k8s.io/utils c2654d5206da6b7b6ace12841e8f359bb89b443c
|
k8s.io/utils e782cd3c129fc98ee807f3c889c0f26eb7c9daf5
|
||||||
sigs.k8s.io/yaml v1.1.0
|
sigs.k8s.io/yaml v1.1.0
|
||||||
|
|
||||||
|
# cni dependencies
|
||||||
|
github.com/containerd/go-cni 49fbd9b210f3c8ee3b7fd3cd797aabaf364627c1
|
||||||
|
github.com/containernetworking/cni v0.7.1
|
||||||
|
github.com/containernetworking/plugins v0.7.6
|
||||||
|
|
||||||
# zfs dependencies
|
# zfs dependencies
|
||||||
github.com/containerd/zfs 2ceb2dbb8154202ed1b8fd32e4ea25b491d7b251
|
github.com/containerd/zfs 2ceb2dbb8154202ed1b8fd32e4ea25b491d7b251
|
||||||
github.com/mistifyio/go-zfs f784269be439d704d3dfa1906f45dd848fed2beb
|
github.com/mistifyio/go-zfs f784269be439d704d3dfa1906f45dd848fed2beb
|
||||||
github.com/google/uuid v1.1.1
|
|
||||||
|
|
||||||
# aufs dependencies
|
# aufs dependencies
|
||||||
github.com/containerd/aufs f894a800659b6e11c1a13084abd1712f346e349c
|
github.com/containerd/aufs f894a800659b6e11c1a13084abd1712f346e349c
|
||||||
|
|
|
@ -21,7 +21,7 @@ var (
|
||||||
Package = "github.com/containerd/containerd"
|
Package = "github.com/containerd/containerd"
|
||||||
|
|
||||||
// Version holds the complete version number. Filled in at linking time.
|
// Version holds the complete version number. Filled in at linking time.
|
||||||
Version = "1.3.0+unknown"
|
Version = "1.3.10+unknown"
|
||||||
|
|
||||||
// Revision is filled with the VCS (e.g. git) revision being used to build
|
// Revision is filled with the VCS (e.g. git) revision being used to build
|
||||||
// the program at linking time.
|
// the program at linking time.
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
# Copyright 2018 The containerd Authors.
|
# Copyright The containerd Authors.
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
# You may obtain a copy of the License at
|
# You may obtain a copy of the License at
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -15,9 +15,13 @@
|
||||||
GO := go
|
GO := go
|
||||||
GOOS := $(shell $(GO) env GOOS)
|
GOOS := $(shell $(GO) env GOOS)
|
||||||
GOARCH := $(shell $(GO) env GOARCH)
|
GOARCH := $(shell $(GO) env GOARCH)
|
||||||
WHALE = "🇩"
|
WHALE := "🇩"
|
||||||
ONI = "👹"
|
ONI := "👹"
|
||||||
EPOCH_TEST_COMMIT := f9e02affccd51702191e5312665a16045ffef8ab
|
ifeq ($(GOOS),windows)
|
||||||
|
WHALE = "+"
|
||||||
|
ONI = "-"
|
||||||
|
endif
|
||||||
|
EPOCH_TEST_COMMIT := 67de3e4ccf2b2a69b8398798af7cfca01abf7a7e
|
||||||
PROJECT := github.com/containerd/cri
|
PROJECT := github.com/containerd/cri
|
||||||
BINDIR := ${DESTDIR}/usr/local/bin
|
BINDIR := ${DESTDIR}/usr/local/bin
|
||||||
BUILD_DIR := _output
|
BUILD_DIR := _output
|
||||||
|
@ -26,35 +30,39 @@ BUILD_DIR := _output
|
||||||
VERSION := $(shell git rev-parse --short HEAD)
|
VERSION := $(shell git rev-parse --short HEAD)
|
||||||
TARBALL_PREFIX := cri-containerd
|
TARBALL_PREFIX := cri-containerd
|
||||||
TARBALL := $(TARBALL_PREFIX)-$(VERSION).$(GOOS)-$(GOARCH).tar.gz
|
TARBALL := $(TARBALL_PREFIX)-$(VERSION).$(GOOS)-$(GOARCH).tar.gz
|
||||||
BUILD_TAGS := seccomp apparmor
|
ifneq ($(GOOS),windows)
|
||||||
|
BUILD_TAGS := seccomp apparmor selinux no_btrfs
|
||||||
|
endif
|
||||||
|
export BUILDTAGS := $(BUILD_TAGS)
|
||||||
# Add `-TEST` suffix to indicate that all binaries built from this repo are for test.
|
# Add `-TEST` suffix to indicate that all binaries built from this repo are for test.
|
||||||
GO_LDFLAGS := -X $(PROJECT)/vendor/github.com/containerd/containerd/version.Version=$(VERSION)-TEST
|
GO_LDFLAGS := -X $(PROJECT)/vendor/github.com/containerd/containerd/version.Version=$(VERSION)-TEST
|
||||||
SOURCES := $(shell find cmd/ pkg/ vendor/ -name '*.go')
|
SOURCES := $(shell find cmd/ pkg/ vendor/ -name '*.go')
|
||||||
PLUGIN_SOURCES := $(shell ls *.go)
|
PLUGIN_SOURCES := $(shell ls *.go)
|
||||||
INTEGRATION_SOURCES := $(shell find integration/ -name '*.go')
|
INTEGRATION_SOURCES := $(shell find integration/ -name '*.go')
|
||||||
|
|
||||||
|
CONTAINERD_BIN := containerd
|
||||||
|
ifeq ($(GOOS),windows)
|
||||||
|
CONTAINERD_BIN := $(CONTAINERD_BIN).exe
|
||||||
|
endif
|
||||||
|
|
||||||
all: binaries
|
all: binaries
|
||||||
|
|
||||||
help: ## this help
|
help: ## this help
|
||||||
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z0-9._-]+:.*?## / {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST) | sort
|
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z0-9._-]+:.*?## / {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST) | sort
|
||||||
|
|
||||||
verify: lint gofmt boiler check-vendor ## execute the source code verification tools
|
verify: lint gofmt check-vendor ## execute the source code verification tools
|
||||||
|
|
||||||
version: ## print current cri plugin release version
|
version: ## print current cri plugin release version
|
||||||
@echo $(VERSION)
|
@echo $(VERSION)
|
||||||
|
|
||||||
lint:
|
lint:
|
||||||
@echo "$(WHALE) $@"
|
@echo "$(WHALE) $@"
|
||||||
golangci-lint run --skip-files .*_test.go
|
golangci-lint run
|
||||||
|
|
||||||
gofmt:
|
gofmt:
|
||||||
@echo "$(WHALE) $@"
|
@echo "$(WHALE) $@"
|
||||||
@./hack/verify-gofmt.sh
|
@./hack/verify-gofmt.sh
|
||||||
|
|
||||||
boiler:
|
|
||||||
@echo "$(WHALE) $@"
|
|
||||||
@./hack/verify-boilerplate.sh
|
|
||||||
|
|
||||||
check-vendor:
|
check-vendor:
|
||||||
@echo "$(WHALE) $@"
|
@echo "$(WHALE) $@"
|
||||||
@./hack/verify-vendor.sh
|
@./hack/verify-vendor.sh
|
||||||
|
@ -72,7 +80,7 @@ sync-vendor:
|
||||||
update-vendor: sync-vendor sort-vendor ## Syncs containerd/vendor.conf -> vendor.conf and sorts vendor.conf
|
update-vendor: sync-vendor sort-vendor ## Syncs containerd/vendor.conf -> vendor.conf and sorts vendor.conf
|
||||||
@echo "$(WHALE) $@"
|
@echo "$(WHALE) $@"
|
||||||
|
|
||||||
$(BUILD_DIR)/containerd: $(SOURCES) $(PLUGIN_SOURCES)
|
$(BUILD_DIR)/$(CONTAINERD_BIN): $(SOURCES) $(PLUGIN_SOURCES)
|
||||||
@echo "$(WHALE) $@"
|
@echo "$(WHALE) $@"
|
||||||
$(GO) build -o $@ \
|
$(GO) build -o $@ \
|
||||||
-tags '$(BUILD_TAGS)' \
|
-tags '$(BUILD_TAGS)' \
|
||||||
|
@ -107,29 +115,34 @@ clean: ## cleanup binaries
|
||||||
@echo "$(WHALE) $@"
|
@echo "$(WHALE) $@"
|
||||||
@rm -rf $(BUILD_DIR)/*
|
@rm -rf $(BUILD_DIR)/*
|
||||||
|
|
||||||
binaries: $(BUILD_DIR)/containerd ## build a customized containerd (same result as make containerd)
|
binaries: $(BUILD_DIR)/$(CONTAINERD_BIN) ## build a customized containerd (same result as make containerd)
|
||||||
@echo "$(WHALE) $@"
|
@echo "$(WHALE) $@"
|
||||||
|
|
||||||
static-binaries: GO_LDFLAGS += -extldflags "-fno-PIC -static"
|
static-binaries: GO_LDFLAGS += -extldflags "-fno-PIC -static"
|
||||||
static-binaries: $(BUILD_DIR)/containerd ## build static containerd
|
static-binaries: $(BUILD_DIR)/$(CONTAINERD_BIN) ## build static containerd
|
||||||
@echo "$(WHALE) $@"
|
@echo "$(WHALE) $@"
|
||||||
|
|
||||||
containerd: $(BUILD_DIR)/containerd ## build a customized containerd with CRI plugin for testing
|
containerd: $(BUILD_DIR)/$(CONTAINERD_BIN) ## build a customized containerd with CRI plugin for testing
|
||||||
@echo "$(WHALE) $@"
|
@echo "$(WHALE) $@"
|
||||||
|
|
||||||
install-containerd: containerd ## installs customized containerd to system location
|
install-containerd: containerd ## installs customized containerd to system location
|
||||||
@echo "$(WHALE) $@"
|
@echo "$(WHALE) $@"
|
||||||
@install -D -m 755 $(BUILD_DIR)/containerd $(BINDIR)/containerd
|
@install -D -m 755 $(BUILD_DIR)/$(CONTAINERD_BIN) "$(BINDIR)/$(CONTAINERD_BIN)"
|
||||||
|
|
||||||
install: install-containerd ## installs customized containerd to system location
|
install: install-containerd ## installs customized containerd to system location
|
||||||
@echo "$(WHALE) $@"
|
@echo "$(WHALE) $@"
|
||||||
|
|
||||||
uninstall: ## remove containerd from system location
|
uninstall: ## remove containerd from system location
|
||||||
@echo "$(WHALE) $@"
|
@echo "$(WHALE) $@"
|
||||||
@rm -f $(BINDIR)/containerd
|
@rm -f "$(BINDIR)/$(CONTAINERD_BIN)"
|
||||||
|
|
||||||
|
ifeq ($(GOOS),windows)
|
||||||
|
$(BUILD_DIR)/$(TARBALL): static-binaries vendor.conf
|
||||||
|
@BUILD_DIR=$(BUILD_DIR) TARBALL=$(TARBALL) VERSION=$(VERSION) ./hack/release-windows.sh
|
||||||
|
else
|
||||||
$(BUILD_DIR)/$(TARBALL): static-binaries vendor.conf
|
$(BUILD_DIR)/$(TARBALL): static-binaries vendor.conf
|
||||||
@BUILD_DIR=$(BUILD_DIR) TARBALL=$(TARBALL) VERSION=$(VERSION) ./hack/release.sh
|
@BUILD_DIR=$(BUILD_DIR) TARBALL=$(TARBALL) VERSION=$(VERSION) ./hack/release.sh
|
||||||
|
endif
|
||||||
|
|
||||||
release: $(BUILD_DIR)/$(TARBALL) ## build release tarball
|
release: $(BUILD_DIR)/$(TARBALL) ## build release tarball
|
||||||
|
|
||||||
|
@ -142,22 +155,29 @@ proto: ## update protobuf of the cri plugin api
|
||||||
@API_PATH=pkg/api/v1 hack/update-proto.sh
|
@API_PATH=pkg/api/v1 hack/update-proto.sh
|
||||||
@API_PATH=pkg/api/runtimeoptions/v1 hack/update-proto.sh
|
@API_PATH=pkg/api/runtimeoptions/v1 hack/update-proto.sh
|
||||||
|
|
||||||
.PHONY: install.deps
|
.PHONY: install.deps .install.deps.linux .install.deps.windows
|
||||||
|
|
||||||
install.deps: ## install dependencies of cri (default 'seccomp apparmor' BUILDTAGS for runc build)
|
ifeq ($(GOOS),windows)
|
||||||
|
install.deps: .install.deps.windows ## install windows deps on windows
|
||||||
|
else
|
||||||
|
install.deps: .install.deps.linux ## install windows deps on linux
|
||||||
|
endif
|
||||||
|
|
||||||
|
.install.deps.linux: ## install dependencies of cri
|
||||||
@echo "$(WHALE) $@"
|
@echo "$(WHALE) $@"
|
||||||
@./hack/install/install-deps.sh
|
@./hack/install/install-deps.sh
|
||||||
|
|
||||||
|
.install.deps.windows: ## install dependencies of cri on windows
|
||||||
|
@echo "$(WHALE) $@"
|
||||||
|
@./hack/install/windows/install-deps.sh
|
||||||
|
|
||||||
.PHONY: .gitvalidation
|
.PHONY: .gitvalidation
|
||||||
# When this is running in travis, it will only check the travis commit range.
|
# make .gitvalidation is only used localy for manual testing
|
||||||
# When running outside travis, it will check from $(EPOCH_TEST_COMMIT)..HEAD.
|
# requires a clone of github.com/containerd/project
|
||||||
|
# containerd/project DCO validation runs automatically with github actions in ci.yml for each pull
|
||||||
.gitvalidation:
|
.gitvalidation:
|
||||||
@echo "$(WHALE) $@"
|
@echo "$(WHALE) $@"
|
||||||
ifeq ($(TRAVIS),true)
|
DCO_VERBOSITY=-v DCO_RANGE=$(EPOCH_TEST_COMMIT)..HEAD ../project/script/validate/dco
|
||||||
git-validation -q -run DCO,short-subject
|
|
||||||
else
|
|
||||||
git-validation -v -run DCO,short-subject -range $(EPOCH_TEST_COMMIT)..HEAD
|
|
||||||
endif
|
|
||||||
|
|
||||||
.PHONY: install.tools .install.gitvalidation .install.golangci-lint .install.vndr
|
.PHONY: install.tools .install.gitvalidation .install.golangci-lint .install.vndr
|
||||||
|
|
||||||
|
@ -170,10 +190,10 @@ install.tools: .install.gitvalidation .install.golangci-lint .install.vndr ## in
|
||||||
|
|
||||||
.install.golangci-lint:
|
.install.golangci-lint:
|
||||||
@echo "$(WHALE) $@"
|
@echo "$(WHALE) $@"
|
||||||
$(GO) get -d github.com/golangci/golangci-lint/cmd/golangci-lint
|
git clone https://github.com/golangci/golangci-lint.git $(GOPATH)/src/github.com/golangci/golangci-lint
|
||||||
@cd $(GOPATH)/src/github.com/golangci/golangci-lint/cmd/golangci-lint; \
|
@cd $(GOPATH)/src/github.com/golangci/golangci-lint/cmd/golangci-lint; \
|
||||||
git checkout v1.18.0; \
|
git checkout v1.18.0; \
|
||||||
go install
|
GO111MODULE=off go install
|
||||||
|
|
||||||
.install.vndr:
|
.install.vndr:
|
||||||
@echo "$(WHALE) $@"
|
@echo "$(WHALE) $@"
|
||||||
|
@ -186,7 +206,6 @@ install.tools: .install.gitvalidation .install.golangci-lint .install.vndr ## in
|
||||||
install-containerd \
|
install-containerd \
|
||||||
release \
|
release \
|
||||||
push \
|
push \
|
||||||
boiler \
|
|
||||||
clean \
|
clean \
|
||||||
default \
|
default \
|
||||||
gofmt \
|
gofmt \
|
||||||
|
|
|
@ -63,6 +63,10 @@ func initCRIService(ic *plugin.InitContext) (interface{}, error) {
|
||||||
ic.Meta.Exports = map[string]string{"CRIVersion": constants.CRIVersion}
|
ic.Meta.Exports = map[string]string{"CRIVersion": constants.CRIVersion}
|
||||||
ctx := ic.Context
|
ctx := ic.Context
|
||||||
pluginConfig := ic.Config.(*criconfig.PluginConfig)
|
pluginConfig := ic.Config.(*criconfig.PluginConfig)
|
||||||
|
if err := criconfig.ValidatePluginConfig(ctx, pluginConfig); err != nil {
|
||||||
|
return nil, errors.Wrap(err, "invalid plugin config")
|
||||||
|
}
|
||||||
|
|
||||||
c := criconfig.Config{
|
c := criconfig.Config{
|
||||||
PluginConfig: *pluginConfig,
|
PluginConfig: *pluginConfig,
|
||||||
ContainerdRootDir: filepath.Dir(ic.Root),
|
ContainerdRootDir: filepath.Dir(ic.Root),
|
||||||
|
@ -72,10 +76,6 @@ func initCRIService(ic *plugin.InitContext) (interface{}, error) {
|
||||||
}
|
}
|
||||||
log.G(ctx).Infof("Start cri plugin with config %+v", c)
|
log.G(ctx).Infof("Start cri plugin with config %+v", c)
|
||||||
|
|
||||||
if err := criconfig.ValidatePluginConfig(ctx, pluginConfig); err != nil {
|
|
||||||
return nil, errors.Wrap(err, "invalid plugin config")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := setGLogLevel(); err != nil {
|
if err := setGLogLevel(); err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to set glog level")
|
return nil, errors.Wrap(err, "failed to set glog level")
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,6 +122,7 @@ type AuthConfig struct {
|
||||||
|
|
||||||
// TLSConfig contains the CA/Cert/Key used for a registry
|
// TLSConfig contains the CA/Cert/Key used for a registry
|
||||||
type TLSConfig struct {
|
type TLSConfig struct {
|
||||||
|
InsecureSkipVerify bool `toml:"insecure_skip_verify" json:"insecure_skip_verify"`
|
||||||
CAFile string `toml:"ca_file" json:"caFile"`
|
CAFile string `toml:"ca_file" json:"caFile"`
|
||||||
CertFile string `toml:"cert_file" json:"certFile"`
|
CertFile string `toml:"cert_file" json:"certFile"`
|
||||||
KeyFile string `toml:"key_file" json:"keyFile"`
|
KeyFile string `toml:"key_file" json:"keyFile"`
|
||||||
|
|
|
@ -265,7 +265,7 @@ func WithMounts(osi osinterface.OS, config *runtime.ContainerConfig, extra []*ru
|
||||||
}
|
}
|
||||||
|
|
||||||
if mount.GetSelinuxRelabel() {
|
if mount.GetSelinuxRelabel() {
|
||||||
if err := label.Relabel(src, mountLabel, true); err != nil && err != unix.ENOTSUP {
|
if err := label.Relabel(src, mountLabel, false); err != nil && err != unix.ENOTSUP {
|
||||||
return errors.Wrapf(err, "relabel %q with %q failed", src, mountLabel)
|
return errors.Wrapf(err, "relabel %q with %q failed", src, mountLabel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The runc 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 seccomp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
// IsEnabled returns if the kernel has been configured to support seccomp.
|
||||||
|
// From https://github.com/opencontainers/runc/blob/v1.0.0-rc91/libcontainer/seccomp/seccomp_linux.go#L86-L102
|
||||||
|
func IsEnabled() bool {
|
||||||
|
// Try to read from /proc/self/status for kernels > 3.8
|
||||||
|
s, err := parseStatusFile("/proc/self/status")
|
||||||
|
if err != nil {
|
||||||
|
// Check if Seccomp is supported, via CONFIG_SECCOMP.
|
||||||
|
if err := unix.Prctl(unix.PR_GET_SECCOMP, 0, 0, 0, 0); err != unix.EINVAL {
|
||||||
|
// Make sure the kernel has CONFIG_SECCOMP_FILTER.
|
||||||
|
if err := unix.Prctl(unix.PR_SET_SECCOMP, unix.SECCOMP_MODE_FILTER, 0, 0, 0); err != unix.EINVAL {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
_, ok := s["Seccomp"]
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseStatusFile is from https://github.com/opencontainers/runc/blob/v1.0.0-rc91/libcontainer/seccomp/seccomp_linux.go#L243-L268
|
||||||
|
func parseStatusFile(path string) (map[string]string, error) {
|
||||||
|
f, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
s := bufio.NewScanner(f)
|
||||||
|
status := make(map[string]string)
|
||||||
|
|
||||||
|
for s.Scan() {
|
||||||
|
text := s.Text()
|
||||||
|
parts := strings.Split(text, ":")
|
||||||
|
|
||||||
|
if len(parts) <= 1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
status[parts[0]] = parts[1]
|
||||||
|
}
|
||||||
|
if err := s.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return status, nil
|
||||||
|
}
|
23
vendor/github.com/containerd/cri/pkg/seccomp/seccomp_unsupported.go
generated
vendored
Normal file
23
vendor/github.com/containerd/cri/pkg/seccomp/seccomp_unsupported.go
generated
vendored
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
// +build !linux
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package seccomp
|
||||||
|
|
||||||
|
func IsEnabled() bool {
|
||||||
|
return false
|
||||||
|
}
|
|
@ -39,6 +39,8 @@ import (
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
|
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
runtimespec "github.com/opencontainers/runtime-spec/specs-go"
|
runtimespec "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
selinux "github.com/opencontainers/selinux/go-selinux"
|
||||||
|
"github.com/opencontainers/selinux/go-selinux/label"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
||||||
|
@ -173,6 +175,18 @@ func (c *criService) CreateContainer(ctx context.Context, r *runtime.CreateConta
|
||||||
return nil, errors.Wrapf(err, "failed to generate container %q spec", id)
|
return nil, errors.Wrapf(err, "failed to generate container %q spec", id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
meta.ProcessLabel = spec.Process.SelinuxLabel
|
||||||
|
if config.GetLinux().GetSecurityContext().GetPrivileged() {
|
||||||
|
// If privileged don't set the SELinux label but still record it on the container so
|
||||||
|
// the unused MCS label can be release later
|
||||||
|
spec.Process.SelinuxLabel = ""
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if retErr != nil {
|
||||||
|
selinux.ReleaseLabel(spec.Process.SelinuxLabel)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
log.G(ctx).Debugf("Container %q spec: %#+v", id, spew.NewFormatter(spec))
|
log.G(ctx).Debugf("Container %q spec: %#+v", id, spew.NewFormatter(spec))
|
||||||
|
|
||||||
// Set snapshotter before any other options.
|
// Set snapshotter before any other options.
|
||||||
|
@ -324,7 +338,7 @@ func (c *criService) CreateContainer(ctx context.Context, r *runtime.CreateConta
|
||||||
|
|
||||||
func (c *criService) generateContainerSpec(id string, sandboxID string, sandboxPid uint32, config *runtime.ContainerConfig,
|
func (c *criService) generateContainerSpec(id string, sandboxID string, sandboxPid uint32, config *runtime.ContainerConfig,
|
||||||
sandboxConfig *runtime.PodSandboxConfig, imageConfig *imagespec.ImageConfig, extraMounts []*runtime.Mount,
|
sandboxConfig *runtime.PodSandboxConfig, imageConfig *imagespec.ImageConfig, extraMounts []*runtime.Mount,
|
||||||
ociRuntime config.Runtime) (*runtimespec.Spec, error) {
|
ociRuntime config.Runtime) (retSpec *runtimespec.Spec, retErr error) {
|
||||||
|
|
||||||
specOpts := []oci.SpecOpts{
|
specOpts := []oci.SpecOpts{
|
||||||
customopts.WithoutRunMount,
|
customopts.WithoutRunMount,
|
||||||
|
@ -359,18 +373,36 @@ func (c *criService) generateContainerSpec(id string, sandboxID string, sandboxP
|
||||||
|
|
||||||
// Apply envs from image config first, so that envs from container config
|
// Apply envs from image config first, so that envs from container config
|
||||||
// can override them.
|
// can override them.
|
||||||
env := imageConfig.Env
|
env := append([]string{}, imageConfig.Env...)
|
||||||
for _, e := range config.GetEnvs() {
|
for _, e := range config.GetEnvs() {
|
||||||
env = append(env, e.GetKey()+"="+e.GetValue())
|
env = append(env, e.GetKey()+"="+e.GetValue())
|
||||||
}
|
}
|
||||||
specOpts = append(specOpts, oci.WithEnv(env))
|
specOpts = append(specOpts, oci.WithEnv(env))
|
||||||
|
|
||||||
securityContext := config.GetLinux().GetSecurityContext()
|
securityContext := config.GetLinux().GetSecurityContext()
|
||||||
selinuxOpt := securityContext.GetSelinuxOptions()
|
labelOptions, err := toLabel(securityContext.GetSelinuxOptions())
|
||||||
processLabel, mountLabel, err := initSelinuxOpts(selinuxOpt)
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(labelOptions) == 0 { // Use pod level SELinux config
|
||||||
|
if sandbox, err := c.sandboxStore.Get(sandboxID); err == nil {
|
||||||
|
labelOptions, err = selinux.DupSecOpt(sandbox.ProcessLabel)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
processLabel, mountLabel, err := label.InitLabels(labelOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "failed to init selinux options %+v", securityContext.GetSelinuxOptions())
|
return nil, errors.Wrapf(err, "failed to init selinux options %+v", securityContext.GetSelinuxOptions())
|
||||||
}
|
}
|
||||||
|
defer func() {
|
||||||
|
if retErr != nil {
|
||||||
|
selinux.ReleaseLabel(processLabel)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
specOpts = append(specOpts, customopts.WithMounts(c.os, config, extraMounts, mountLabel))
|
specOpts = append(specOpts, customopts.WithMounts(c.os, config, extraMounts, mountLabel))
|
||||||
|
|
||||||
if !c.config.DisableProcMount {
|
if !c.config.DisableProcMount {
|
||||||
|
@ -463,8 +495,8 @@ func (c *criService) generateVolumeMounts(containerRootDir string, criMounts []*
|
||||||
mounts = append(mounts, &runtime.Mount{
|
mounts = append(mounts, &runtime.Mount{
|
||||||
ContainerPath: dst,
|
ContainerPath: dst,
|
||||||
HostPath: src,
|
HostPath: src,
|
||||||
|
SelinuxRelabel: true,
|
||||||
// Use default mount propagation.
|
// Use default mount propagation.
|
||||||
// TODO(random-liu): What about selinux relabel?
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return mounts
|
return mounts
|
||||||
|
@ -518,6 +550,7 @@ func (c *criService) generateContainerMounts(sandboxID string, config *runtime.C
|
||||||
ContainerPath: devShm,
|
ContainerPath: devShm,
|
||||||
HostPath: sandboxDevShm,
|
HostPath: sandboxDevShm,
|
||||||
Readonly: false,
|
Readonly: false,
|
||||||
|
SelinuxRelabel: sandboxDevShm != devShm,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return mounts
|
return mounts
|
||||||
|
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"github.com/containerd/containerd/log"
|
"github.com/containerd/containerd/log"
|
||||||
"github.com/docker/docker/pkg/system"
|
"github.com/docker/docker/pkg/system"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
||||||
|
|
||||||
|
@ -30,7 +31,6 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// RemoveContainer removes the container.
|
// RemoveContainer removes the container.
|
||||||
// TODO(random-liu): Forcibly stop container if it's running.
|
|
||||||
func (c *criService) RemoveContainer(ctx context.Context, r *runtime.RemoveContainerRequest) (_ *runtime.RemoveContainerResponse, retErr error) {
|
func (c *criService) RemoveContainer(ctx context.Context, r *runtime.RemoveContainerRequest) (_ *runtime.RemoveContainerResponse, retErr error) {
|
||||||
container, err := c.containerStore.Get(r.GetContainerId())
|
container, err := c.containerStore.Get(r.GetContainerId())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -43,6 +43,17 @@ func (c *criService) RemoveContainer(ctx context.Context, r *runtime.RemoveConta
|
||||||
}
|
}
|
||||||
id := container.ID
|
id := container.ID
|
||||||
|
|
||||||
|
// Forcibly stop the containers if they are in running or unknown state
|
||||||
|
state := container.Status.Get().State()
|
||||||
|
if state == runtime.ContainerState_CONTAINER_RUNNING ||
|
||||||
|
state == runtime.ContainerState_CONTAINER_UNKNOWN {
|
||||||
|
logrus.Infof("Forcibly stopping container %q", id)
|
||||||
|
if err := c.stopContainer(ctx, container, 0); err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "failed to forcibly stop container %q", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Set removing state to prevent other start/remove operations against this container
|
// Set removing state to prevent other start/remove operations against this container
|
||||||
// while it's being removed.
|
// while it's being removed.
|
||||||
if err := setContainerRemoving(container); err != nil {
|
if err := setContainerRemoving(container); err != nil {
|
||||||
|
|
|
@ -333,6 +333,12 @@ func handleContainerExit(ctx context.Context, e *eventtypes.TaskExit, cntr conta
|
||||||
status.Pid = 0
|
status.Pid = 0
|
||||||
status.FinishedAt = e.ExitedAt.UnixNano()
|
status.FinishedAt = e.ExitedAt.UnixNano()
|
||||||
status.ExitCode = int32(e.ExitStatus)
|
status.ExitCode = int32(e.ExitStatus)
|
||||||
|
// Unknown state can only transit to EXITED state, so we need
|
||||||
|
// to handle unknown state here.
|
||||||
|
if status.Unknown {
|
||||||
|
logrus.Debugf("Container %q transited from UNKNOWN to EXITED", cntr.ID)
|
||||||
|
status.Unknown = false
|
||||||
|
}
|
||||||
return status, nil
|
return status, nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -298,47 +298,63 @@ func (c *criService) ensureImageExists(ctx context.Context, ref string, config *
|
||||||
return &newImage, nil
|
return &newImage, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func initSelinuxOpts(selinuxOpt *runtime.SELinuxOption) (string, string, error) {
|
func toLabel(selinuxOptions *runtime.SELinuxOption) ([]string, error) {
|
||||||
if selinuxOpt == nil {
|
var labels []string
|
||||||
return "", "", nil
|
|
||||||
|
if selinuxOptions == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
if err := checkSelinuxLevel(selinuxOptions.Level); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if selinuxOptions.User != "" {
|
||||||
|
labels = append(labels, "user:"+selinuxOptions.User)
|
||||||
|
}
|
||||||
|
if selinuxOptions.Role != "" {
|
||||||
|
labels = append(labels, "role:"+selinuxOptions.Role)
|
||||||
|
}
|
||||||
|
if selinuxOptions.Type != "" {
|
||||||
|
labels = append(labels, "type:"+selinuxOptions.Type)
|
||||||
|
}
|
||||||
|
if selinuxOptions.Level != "" {
|
||||||
|
labels = append(labels, "level:"+selinuxOptions.Level)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Should ignored selinuxOpts if they are incomplete.
|
return labels, nil
|
||||||
if selinuxOpt.GetUser() == "" ||
|
}
|
||||||
selinuxOpt.GetRole() == "" ||
|
|
||||||
selinuxOpt.GetType() == "" {
|
|
||||||
return "", "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure the format of "level" is correct.
|
func initLabelsFromOpt(selinuxOpts *runtime.SELinuxOption) (string, string, error) {
|
||||||
ok, err := checkSelinuxLevel(selinuxOpt.GetLevel())
|
labels, err := toLabel(selinuxOpts)
|
||||||
if err != nil || !ok {
|
|
||||||
return "", "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
labelOpts := fmt.Sprintf("%s:%s:%s:%s",
|
|
||||||
selinuxOpt.GetUser(),
|
|
||||||
selinuxOpt.GetRole(),
|
|
||||||
selinuxOpt.GetType(),
|
|
||||||
selinuxOpt.GetLevel())
|
|
||||||
|
|
||||||
options, err := label.DupSecOpt(labelOpts)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
|
return label.InitLabels(labels)
|
||||||
|
}
|
||||||
|
|
||||||
|
func initLabels(options []string) (string, string, error) {
|
||||||
|
for _, opt := range options {
|
||||||
|
if strings.HasPrefix(opt, "level:") {
|
||||||
|
if err := checkSelinuxLevel(strings.TrimPrefix(opt, "level:")); err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return label.InitLabels(options)
|
return label.InitLabels(options)
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkSelinuxLevel(level string) (bool, error) {
|
func checkSelinuxLevel(level string) error {
|
||||||
if len(level) == 0 {
|
if len(level) == 0 {
|
||||||
return true, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
matched, err := regexp.MatchString(`^s\d(-s\d)??(:c\d{1,4}((.c\d{1,4})?,c\d{1,4})*(.c\d{1,4})?(,c\d{1,4}(.c\d{1,4})?)*)?$`, level)
|
matched, err := regexp.MatchString(`^s\d(-s\d)??(:c\d{1,4}(\.c\d{1,4})?(,c\d{1,4}(\.c\d{1,4})?)*)?$`, level)
|
||||||
if err != nil || !matched {
|
if err != nil {
|
||||||
return false, errors.Wrapf(err, "the format of 'level' %q is not correct", level)
|
return errors.Wrapf(err, "the format of 'level' %q is not correct", level)
|
||||||
}
|
}
|
||||||
return true, nil
|
if !matched {
|
||||||
|
return fmt.Errorf("the format of 'level' %q is not correct", level)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// isInCRIMounts checks whether a destination is in CRI mount list.
|
// isInCRIMounts checks whether a destination is in CRI mount list.
|
||||||
|
@ -465,6 +481,7 @@ func unknownContainerStatus() containerstore.Status {
|
||||||
FinishedAt: 0,
|
FinishedAt: 0,
|
||||||
ExitCode: unknownExitCode,
|
ExitCode: unknownExitCode,
|
||||||
Reason: unknownExitReason,
|
Reason: unknownExitReason,
|
||||||
|
Unknown: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -253,22 +253,28 @@ func (c *criService) updateImage(ctx context.Context, r string) error {
|
||||||
// getTLSConfig returns a TLSConfig configured with a CA/Cert/Key specified by registryTLSConfig
|
// getTLSConfig returns a TLSConfig configured with a CA/Cert/Key specified by registryTLSConfig
|
||||||
func (c *criService) getTLSConfig(registryTLSConfig criconfig.TLSConfig) (*tls.Config, error) {
|
func (c *criService) getTLSConfig(registryTLSConfig criconfig.TLSConfig) (*tls.Config, error) {
|
||||||
var (
|
var (
|
||||||
|
tlsConfig = &tls.Config{}
|
||||||
cert tls.Certificate
|
cert tls.Certificate
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
if registryTLSConfig.CertFile != "" && registryTLSConfig.KeyFile != "" {
|
|
||||||
cert, err = tls.LoadX509KeyPair(registryTLSConfig.CertFile, registryTLSConfig.KeyFile)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "failed to load cert file")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if registryTLSConfig.CertFile != "" && registryTLSConfig.KeyFile == "" {
|
if registryTLSConfig.CertFile != "" && registryTLSConfig.KeyFile == "" {
|
||||||
return nil, errors.Errorf("cert file %q was specified, but no corresponding key file was specified", registryTLSConfig.CertFile)
|
return nil, errors.Errorf("cert file %q was specified, but no corresponding key file was specified", registryTLSConfig.CertFile)
|
||||||
}
|
}
|
||||||
if registryTLSConfig.CertFile == "" && registryTLSConfig.KeyFile != "" {
|
if registryTLSConfig.CertFile == "" && registryTLSConfig.KeyFile != "" {
|
||||||
return nil, errors.Errorf("key file %q was specified, but no corresponding cert file was specified", registryTLSConfig.KeyFile)
|
return nil, errors.Errorf("key file %q was specified, but no corresponding cert file was specified", registryTLSConfig.KeyFile)
|
||||||
}
|
}
|
||||||
|
if registryTLSConfig.CertFile != "" && registryTLSConfig.KeyFile != "" {
|
||||||
|
cert, err = tls.LoadX509KeyPair(registryTLSConfig.CertFile, registryTLSConfig.KeyFile)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "failed to load cert file")
|
||||||
|
}
|
||||||
|
if len(cert.Certificate) != 0 {
|
||||||
|
tlsConfig.Certificates = []tls.Certificate{cert}
|
||||||
|
}
|
||||||
|
tlsConfig.BuildNameToCertificate() // nolint:staticcheck
|
||||||
|
}
|
||||||
|
|
||||||
|
if registryTLSConfig.CAFile != "" {
|
||||||
caCertPool, err := x509.SystemCertPool()
|
caCertPool, err := x509.SystemCertPool()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to get system cert pool")
|
return nil, errors.Wrap(err, "failed to get system cert pool")
|
||||||
|
@ -278,14 +284,10 @@ func (c *criService) getTLSConfig(registryTLSConfig criconfig.TLSConfig) (*tls.C
|
||||||
return nil, errors.Wrap(err, "failed to load CA file")
|
return nil, errors.Wrap(err, "failed to load CA file")
|
||||||
}
|
}
|
||||||
caCertPool.AppendCertsFromPEM(caCert)
|
caCertPool.AppendCertsFromPEM(caCert)
|
||||||
|
tlsConfig.RootCAs = caCertPool
|
||||||
|
}
|
||||||
|
|
||||||
tlsConfig := &tls.Config{
|
tlsConfig.InsecureSkipVerify = registryTLSConfig.InsecureSkipVerify
|
||||||
RootCAs: caCertPool,
|
|
||||||
}
|
|
||||||
if len(cert.Certificate) != 0 {
|
|
||||||
tlsConfig.Certificates = []tls.Certificate{cert}
|
|
||||||
}
|
|
||||||
tlsConfig.BuildNameToCertificate()
|
|
||||||
return tlsConfig, nil
|
return tlsConfig, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -307,7 +307,9 @@ func (c *criService) loadContainer(ctx context.Context, cntr containerd.Containe
|
||||||
}()
|
}()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.G(ctx).WithError(err).Errorf("Failed to load container status for %q", id)
|
log.G(ctx).WithError(err).Errorf("Failed to load container status for %q", id)
|
||||||
status = unknownContainerStatus()
|
// Only set the unknown field in this case, because other fields may
|
||||||
|
// contain useful information loaded from the checkpoint.
|
||||||
|
status.Unknown = true
|
||||||
}
|
}
|
||||||
opts := []containerstore.Opts{
|
opts := []containerstore.Opts{
|
||||||
containerstore.WithStatus(status, containerDir),
|
containerstore.WithStatus(status, containerDir),
|
||||||
|
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"github.com/containerd/containerd/log"
|
"github.com/containerd/containerd/log"
|
||||||
"github.com/docker/docker/pkg/system"
|
"github.com/docker/docker/pkg/system"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
||||||
|
|
||||||
|
@ -49,7 +50,10 @@ func (c *criService) RemovePodSandbox(ctx context.Context, r *runtime.RemovePodS
|
||||||
// Return error if sandbox container is still running or unknown.
|
// Return error if sandbox container is still running or unknown.
|
||||||
state := sandbox.Status.Get().State
|
state := sandbox.Status.Get().State
|
||||||
if state == sandboxstore.StateReady || state == sandboxstore.StateUnknown {
|
if state == sandboxstore.StateReady || state == sandboxstore.StateUnknown {
|
||||||
return nil, errors.Errorf("sandbox container %q is not fully stopped", id)
|
logrus.Infof("Forcibly stopping sandbox %q", id)
|
||||||
|
if err := c.stopPodSandbox(ctx, sandbox); err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "failed to forcibly stop sandbox %q", id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return error if sandbox network namespace is not closed yet.
|
// Return error if sandbox network namespace is not closed yet.
|
||||||
|
|
|
@ -34,6 +34,7 @@ import (
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
|
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
runtimespec "github.com/opencontainers/runtime-spec/specs-go"
|
runtimespec "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
selinux "github.com/opencontainers/selinux/go-selinux"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
|
@ -158,6 +159,18 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox
|
||||||
return nil, errors.Wrap(err, "failed to generate sandbox container spec")
|
return nil, errors.Wrap(err, "failed to generate sandbox container spec")
|
||||||
}
|
}
|
||||||
log.G(ctx).Debugf("Sandbox container %q spec: %#+v", id, spew.NewFormatter(spec))
|
log.G(ctx).Debugf("Sandbox container %q spec: %#+v", id, spew.NewFormatter(spec))
|
||||||
|
sandbox.ProcessLabel = spec.Process.SelinuxLabel
|
||||||
|
defer func() {
|
||||||
|
if retErr != nil {
|
||||||
|
selinux.ReleaseLabel(sandbox.ProcessLabel)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if securityContext.GetPrivileged() {
|
||||||
|
// If privileged don't set selinux label, but we still record the MCS label so that
|
||||||
|
// the unused label can be freed later.
|
||||||
|
spec.Process.SelinuxLabel = ""
|
||||||
|
}
|
||||||
|
|
||||||
var specOpts []oci.SpecOpts
|
var specOpts []oci.SpecOpts
|
||||||
userstr, err := generateUserString(
|
userstr, err := generateUserString(
|
||||||
|
@ -271,7 +284,7 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox
|
||||||
|
|
||||||
var taskOpts []containerd.NewTaskOpts
|
var taskOpts []containerd.NewTaskOpts
|
||||||
// TODO(random-liu): Remove this after shim v1 is deprecated.
|
// TODO(random-liu): Remove this after shim v1 is deprecated.
|
||||||
if c.config.NoPivot && ociRuntime.Type == plugin.RuntimeRuncV1 {
|
if c.config.NoPivot && (ociRuntime.Type == plugin.RuntimeRuncV1 || ociRuntime.Type == plugin.RuntimeRuncV2) {
|
||||||
taskOpts = append(taskOpts, containerd.WithNoPivotRoot)
|
taskOpts = append(taskOpts, containerd.WithNoPivotRoot)
|
||||||
}
|
}
|
||||||
// We don't need stdio for sandbox container.
|
// We don't need stdio for sandbox container.
|
||||||
|
@ -328,7 +341,7 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *criService) generateSandboxContainerSpec(id string, config *runtime.PodSandboxConfig,
|
func (c *criService) generateSandboxContainerSpec(id string, config *runtime.PodSandboxConfig,
|
||||||
imageConfig *imagespec.ImageConfig, nsPath string, runtimePodAnnotations []string) (*runtimespec.Spec, error) {
|
imageConfig *imagespec.ImageConfig, nsPath string, runtimePodAnnotations []string) (retSpec *runtimespec.Spec, retErr error) {
|
||||||
// Creates a spec Generator with the default spec.
|
// Creates a spec Generator with the default spec.
|
||||||
// TODO(random-liu): [P1] Compare the default settings with docker and containerd default.
|
// TODO(random-liu): [P1] Compare the default settings with docker and containerd default.
|
||||||
specOpts := []oci.SpecOpts{
|
specOpts := []oci.SpecOpts{
|
||||||
|
@ -403,11 +416,15 @@ func (c *criService) generateSandboxContainerSpec(id string, config *runtime.Pod
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
|
|
||||||
selinuxOpt := securityContext.GetSelinuxOptions()
|
processLabel, mountLabel, err := initLabelsFromOpt(securityContext.GetSelinuxOptions())
|
||||||
processLabel, mountLabel, err := initSelinuxOpts(selinuxOpt)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "failed to init selinux options %+v", securityContext.GetSelinuxOptions())
|
return nil, errors.Wrapf(err, "failed to init selinux options %+v", securityContext.GetSelinuxOptions())
|
||||||
}
|
}
|
||||||
|
defer func() {
|
||||||
|
if retErr != nil && processLabel != "" {
|
||||||
|
selinux.ReleaseLabel(processLabel)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
supplementalGroups := securityContext.GetSupplementalGroups()
|
supplementalGroups := securityContext.GetSupplementalGroups()
|
||||||
specOpts = append(specOpts,
|
specOpts = append(specOpts,
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2017 The Kubernetes Authors.
|
Copyright The containerd Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
You may obtain a copy of the License at
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
Unless required by applicable law or agreed to in writing, software
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package server
|
package server
|
||||||
|
@ -40,6 +40,15 @@ func (c *criService) StopPodSandbox(ctx context.Context, r *runtime.StopPodSandb
|
||||||
return nil, errors.Wrapf(err, "an error occurred when try to find sandbox %q",
|
return nil, errors.Wrapf(err, "an error occurred when try to find sandbox %q",
|
||||||
r.GetPodSandboxId())
|
r.GetPodSandboxId())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := c.stopPodSandbox(ctx, sandbox); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &runtime.StopPodSandboxResponse{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *criService) stopPodSandbox(ctx context.Context, sandbox sandboxstore.Sandbox) error {
|
||||||
// Use the full sandbox id.
|
// Use the full sandbox id.
|
||||||
id := sandbox.ID
|
id := sandbox.ID
|
||||||
|
|
||||||
|
@ -53,20 +62,20 @@ func (c *criService) StopPodSandbox(ctx context.Context, r *runtime.StopPodSandb
|
||||||
}
|
}
|
||||||
// Forcibly stop the container. Do not use `StopContainer`, because it introduces a race
|
// Forcibly stop the container. Do not use `StopContainer`, because it introduces a race
|
||||||
// if a container is removed after list.
|
// if a container is removed after list.
|
||||||
if err = c.stopContainer(ctx, container, 0); err != nil {
|
if err := c.stopContainer(ctx, container, 0); err != nil {
|
||||||
return nil, errors.Wrapf(err, "failed to stop container %q", container.ID)
|
return errors.Wrapf(err, "failed to stop container %q", container.ID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := c.unmountSandboxFiles(id, sandbox.Config); err != nil {
|
if err := c.unmountSandboxFiles(id, sandbox.Config); err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to unmount sandbox files")
|
return errors.Wrap(err, "failed to unmount sandbox files")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only stop sandbox container when it's running or unknown.
|
// Only stop sandbox container when it's running or unknown.
|
||||||
state := sandbox.Status.Get().State
|
state := sandbox.Status.Get().State
|
||||||
if state == sandboxstore.StateReady || state == sandboxstore.StateUnknown {
|
if state == sandboxstore.StateReady || state == sandboxstore.StateUnknown {
|
||||||
if err := c.stopSandboxContainer(ctx, sandbox); err != nil {
|
if err := c.stopSandboxContainer(ctx, sandbox); err != nil {
|
||||||
return nil, errors.Wrapf(err, "failed to stop sandbox container %q in %q state", id, state)
|
return errors.Wrapf(err, "failed to stop sandbox container %q in %q state", id, state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,21 +84,21 @@ func (c *criService) StopPodSandbox(ctx context.Context, r *runtime.StopPodSandb
|
||||||
// Use empty netns path if netns is not available. This is defined in:
|
// Use empty netns path if netns is not available. This is defined in:
|
||||||
// https://github.com/containernetworking/cni/blob/v0.7.0-alpha1/SPEC.md
|
// https://github.com/containernetworking/cni/blob/v0.7.0-alpha1/SPEC.md
|
||||||
if closed, err := sandbox.NetNS.Closed(); err != nil {
|
if closed, err := sandbox.NetNS.Closed(); err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to check network namespace closed")
|
return errors.Wrap(err, "failed to check network namespace closed")
|
||||||
} else if closed {
|
} else if closed {
|
||||||
sandbox.NetNSPath = ""
|
sandbox.NetNSPath = ""
|
||||||
}
|
}
|
||||||
if err := c.teardownPodNetwork(ctx, sandbox); err != nil {
|
if err := c.teardownPodNetwork(ctx, sandbox); err != nil {
|
||||||
return nil, errors.Wrapf(err, "failed to destroy network for sandbox %q", id)
|
return errors.Wrapf(err, "failed to destroy network for sandbox %q", id)
|
||||||
}
|
}
|
||||||
if err = sandbox.NetNS.Remove(); err != nil {
|
if err := sandbox.NetNS.Remove(); err != nil {
|
||||||
return nil, errors.Wrapf(err, "failed to remove network namespace for sandbox %q", id)
|
return errors.Wrapf(err, "failed to remove network namespace for sandbox %q", id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.G(ctx).Infof("TearDown network for sandbox %q successfully", id)
|
log.G(ctx).Infof("TearDown network for sandbox %q successfully", id)
|
||||||
|
|
||||||
return &runtime.StopPodSandboxResponse{}, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// stopSandboxContainer kills the sandbox container.
|
// stopSandboxContainer kills the sandbox container.
|
||||||
|
|
|
@ -25,9 +25,9 @@ import (
|
||||||
|
|
||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
"github.com/containerd/containerd/plugin"
|
"github.com/containerd/containerd/plugin"
|
||||||
|
"github.com/containerd/cri/pkg/store/label"
|
||||||
cni "github.com/containerd/go-cni"
|
cni "github.com/containerd/go-cni"
|
||||||
runcapparmor "github.com/opencontainers/runc/libcontainer/apparmor"
|
runcapparmor "github.com/opencontainers/runc/libcontainer/apparmor"
|
||||||
runcseccomp "github.com/opencontainers/runc/libcontainer/seccomp"
|
|
||||||
runcsystem "github.com/opencontainers/runc/libcontainer/system"
|
runcsystem "github.com/opencontainers/runc/libcontainer/system"
|
||||||
"github.com/opencontainers/selinux/go-selinux"
|
"github.com/opencontainers/selinux/go-selinux"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
@ -41,6 +41,7 @@ import (
|
||||||
ctrdutil "github.com/containerd/cri/pkg/containerd/util"
|
ctrdutil "github.com/containerd/cri/pkg/containerd/util"
|
||||||
osinterface "github.com/containerd/cri/pkg/os"
|
osinterface "github.com/containerd/cri/pkg/os"
|
||||||
"github.com/containerd/cri/pkg/registrar"
|
"github.com/containerd/cri/pkg/registrar"
|
||||||
|
"github.com/containerd/cri/pkg/seccomp"
|
||||||
containerstore "github.com/containerd/cri/pkg/store/container"
|
containerstore "github.com/containerd/cri/pkg/store/container"
|
||||||
imagestore "github.com/containerd/cri/pkg/store/image"
|
imagestore "github.com/containerd/cri/pkg/store/image"
|
||||||
sandboxstore "github.com/containerd/cri/pkg/store/sandbox"
|
sandboxstore "github.com/containerd/cri/pkg/store/sandbox"
|
||||||
|
@ -104,14 +105,15 @@ type criService struct {
|
||||||
// NewCRIService returns a new instance of CRIService
|
// NewCRIService returns a new instance of CRIService
|
||||||
func NewCRIService(config criconfig.Config, client *containerd.Client) (CRIService, error) {
|
func NewCRIService(config criconfig.Config, client *containerd.Client) (CRIService, error) {
|
||||||
var err error
|
var err error
|
||||||
|
labels := label.NewStore()
|
||||||
c := &criService{
|
c := &criService{
|
||||||
config: config,
|
config: config,
|
||||||
client: client,
|
client: client,
|
||||||
apparmorEnabled: runcapparmor.IsEnabled() && !config.DisableApparmor,
|
apparmorEnabled: runcapparmor.IsEnabled() && !config.DisableApparmor,
|
||||||
seccompEnabled: runcseccomp.IsEnabled(),
|
seccompEnabled: seccomp.IsEnabled(),
|
||||||
os: osinterface.RealOS{},
|
os: osinterface.RealOS{},
|
||||||
sandboxStore: sandboxstore.NewStore(),
|
sandboxStore: sandboxstore.NewStore(labels),
|
||||||
containerStore: containerstore.NewStore(),
|
containerStore: containerstore.NewStore(labels),
|
||||||
imageStore: imagestore.NewStore(client),
|
imageStore: imagestore.NewStore(client),
|
||||||
snapshotStore: snapshotstore.NewStore(),
|
snapshotStore: snapshotstore.NewStore(),
|
||||||
sandboxNameIndex: registrar.NewRegistrar(),
|
sandboxNameIndex: registrar.NewRegistrar(),
|
||||||
|
|
|
@ -68,7 +68,7 @@ func getStreamListenerMode(c *criService) (streamListenerMode, error) {
|
||||||
|
|
||||||
func newStreamServer(c *criService, addr, port, streamIdleTimeout string) (streaming.Server, error) {
|
func newStreamServer(c *criService, addr, port, streamIdleTimeout string) (streaming.Server, error) {
|
||||||
if addr == "" {
|
if addr == "" {
|
||||||
a, err := k8snet.ChooseBindAddress(nil)
|
a, err := k8snet.ChooseHostInterface()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to get stream server address")
|
return nil, errors.Wrap(err, "failed to get stream server address")
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
|
"github.com/containerd/cri/pkg/store/label"
|
||||||
"github.com/docker/docker/pkg/truncindex"
|
"github.com/docker/docker/pkg/truncindex"
|
||||||
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
||||||
|
|
||||||
|
@ -101,13 +102,15 @@ type Store struct {
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
containers map[string]Container
|
containers map[string]Container
|
||||||
idIndex *truncindex.TruncIndex
|
idIndex *truncindex.TruncIndex
|
||||||
|
labels *label.Store
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewStore creates a container store.
|
// NewStore creates a container store.
|
||||||
func NewStore() *Store {
|
func NewStore(labels *label.Store) *Store {
|
||||||
return &Store{
|
return &Store{
|
||||||
containers: make(map[string]Container),
|
containers: make(map[string]Container),
|
||||||
idIndex: truncindex.NewTruncIndex([]string{}),
|
idIndex: truncindex.NewTruncIndex([]string{}),
|
||||||
|
labels: labels,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,6 +122,9 @@ func (s *Store) Add(c Container) error {
|
||||||
if _, ok := s.containers[c.ID]; ok {
|
if _, ok := s.containers[c.ID]; ok {
|
||||||
return store.ErrAlreadyExist
|
return store.ErrAlreadyExist
|
||||||
}
|
}
|
||||||
|
if err := s.labels.Reserve(c.ProcessLabel); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if err := s.idIndex.Add(c.ID); err != nil {
|
if err := s.idIndex.Add(c.ID); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -165,6 +171,7 @@ func (s *Store) Delete(id string) {
|
||||||
// So we need to return if there are error.
|
// So we need to return if there are error.
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
s.labels.Release(s.containers[id].ProcessLabel)
|
||||||
s.idIndex.Delete(id) // nolint: errcheck
|
s.idIndex.Delete(id) // nolint: errcheck
|
||||||
delete(s.containers, id)
|
delete(s.containers, id)
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,6 +61,8 @@ type Metadata struct {
|
||||||
// StopSignal is the system call signal that will be sent to the container to exit.
|
// StopSignal is the system call signal that will be sent to the container to exit.
|
||||||
// TODO(random-liu): Add integration test for stop signal.
|
// TODO(random-liu): Add integration test for stop signal.
|
||||||
StopSignal string
|
StopSignal string
|
||||||
|
// ProcessLabel is the SELinux process label for the container
|
||||||
|
ProcessLabel string
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalJSON encodes Metadata into bytes in json format.
|
// MarshalJSON encodes Metadata into bytes in json format.
|
||||||
|
|
|
@ -94,10 +94,16 @@ type Status struct {
|
||||||
// Removing indicates that the container is in removing state.
|
// Removing indicates that the container is in removing state.
|
||||||
// This field doesn't need to be checkpointed.
|
// This field doesn't need to be checkpointed.
|
||||||
Removing bool `json:"-"`
|
Removing bool `json:"-"`
|
||||||
|
// Unknown indicates that the container status is not fully loaded.
|
||||||
|
// This field doesn't need to be checkpointed.
|
||||||
|
Unknown bool `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// State returns current state of the container based on the container status.
|
// State returns current state of the container based on the container status.
|
||||||
func (s Status) State() runtime.ContainerState {
|
func (s Status) State() runtime.ContainerState {
|
||||||
|
if s.Unknown {
|
||||||
|
return runtime.ContainerState_CONTAINER_UNKNOWN
|
||||||
|
}
|
||||||
if s.FinishedAt != 0 {
|
if s.FinishedAt != 0 {
|
||||||
return runtime.ContainerState_CONTAINER_EXITED
|
return runtime.ContainerState_CONTAINER_EXITED
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
/*
|
||||||
|
Copyright 2017 The Kubernetes 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 label
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/opencontainers/selinux/go-selinux"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Store struct {
|
||||||
|
sync.Mutex
|
||||||
|
levels map[string]int
|
||||||
|
Releaser func(string)
|
||||||
|
Reserver func(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewStore() *Store {
|
||||||
|
return &Store{
|
||||||
|
levels: map[string]int{},
|
||||||
|
Releaser: selinux.ReleaseLabel,
|
||||||
|
Reserver: selinux.ReserveLabel,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Store) Reserve(label string) error {
|
||||||
|
s.Lock()
|
||||||
|
defer s.Unlock()
|
||||||
|
|
||||||
|
context, err := selinux.NewContext(label)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
level := context["level"]
|
||||||
|
// no reason to count empty
|
||||||
|
if level == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := s.levels[level]; !ok {
|
||||||
|
s.Reserver(label)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.levels[level]++
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Store) Release(label string) {
|
||||||
|
s.Lock()
|
||||||
|
defer s.Unlock()
|
||||||
|
|
||||||
|
context, err := selinux.NewContext(label)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
level := context["level"]
|
||||||
|
if level == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
count, ok := s.levels[level]
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case count == 1:
|
||||||
|
s.Releaser(label)
|
||||||
|
delete(s.levels, level)
|
||||||
|
case count < 1:
|
||||||
|
delete(s.levels, level)
|
||||||
|
case count > 1:
|
||||||
|
s.levels[level] = count - 1
|
||||||
|
}
|
||||||
|
}
|
|
@ -61,6 +61,8 @@ type Metadata struct {
|
||||||
RuntimeHandler string
|
RuntimeHandler string
|
||||||
// CNIresult resulting configuration for attached network namespace interfaces
|
// CNIresult resulting configuration for attached network namespace interfaces
|
||||||
CNIResult *cni.CNIResult
|
CNIResult *cni.CNIResult
|
||||||
|
// ProcessLabel is the SELinux process label for the container
|
||||||
|
ProcessLabel string
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalJSON encodes Metadata into bytes in json format.
|
// MarshalJSON encodes Metadata into bytes in json format.
|
||||||
|
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
|
"github.com/containerd/cri/pkg/store/label"
|
||||||
"github.com/docker/docker/pkg/truncindex"
|
"github.com/docker/docker/pkg/truncindex"
|
||||||
|
|
||||||
"github.com/containerd/cri/pkg/netns"
|
"github.com/containerd/cri/pkg/netns"
|
||||||
|
@ -62,13 +63,15 @@ type Store struct {
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
sandboxes map[string]Sandbox
|
sandboxes map[string]Sandbox
|
||||||
idIndex *truncindex.TruncIndex
|
idIndex *truncindex.TruncIndex
|
||||||
|
labels *label.Store
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewStore creates a sandbox store.
|
// NewStore creates a sandbox store.
|
||||||
func NewStore() *Store {
|
func NewStore(labels *label.Store) *Store {
|
||||||
return &Store{
|
return &Store{
|
||||||
sandboxes: make(map[string]Sandbox),
|
sandboxes: make(map[string]Sandbox),
|
||||||
idIndex: truncindex.NewTruncIndex([]string{}),
|
idIndex: truncindex.NewTruncIndex([]string{}),
|
||||||
|
labels: labels,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,6 +82,9 @@ func (s *Store) Add(sb Sandbox) error {
|
||||||
if _, ok := s.sandboxes[sb.ID]; ok {
|
if _, ok := s.sandboxes[sb.ID]; ok {
|
||||||
return store.ErrAlreadyExist
|
return store.ErrAlreadyExist
|
||||||
}
|
}
|
||||||
|
if err := s.labels.Reserve(sb.ProcessLabel); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if err := s.idIndex.Add(sb.ID); err != nil {
|
if err := s.idIndex.Add(sb.ID); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -125,6 +131,7 @@ func (s *Store) Delete(id string) {
|
||||||
// So we need to return if there are error.
|
// So we need to return if there are error.
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
s.labels.Release(s.sandboxes[id].ProcessLabel)
|
||||||
s.idIndex.Delete(id) // nolint: errcheck
|
s.idIndex.Delete(id) // nolint: errcheck
|
||||||
delete(s.sandboxes, id)
|
delete(s.sandboxes, id)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,81 +1,87 @@
|
||||||
# cri dependencies
|
# cri dependencies
|
||||||
github.com/tchap/go-patricia v2.2.6
|
|
||||||
github.com/opencontainers/selinux v1.2.2
|
|
||||||
github.com/docker/docker 86f080cff0914e9694068ed78d503701667c4c00
|
|
||||||
github.com/docker/distribution 0d3efadf0154c2b8a4e7b6621fff9809655cc580
|
github.com/docker/distribution 0d3efadf0154c2b8a4e7b6621fff9809655cc580
|
||||||
|
github.com/docker/docker 86f080cff0914e9694068ed78d503701667c4c00
|
||||||
|
github.com/opencontainers/selinux v1.2.2
|
||||||
|
github.com/tchap/go-patricia v2.2.6
|
||||||
|
|
||||||
# containerd dependencies
|
# containerd dependencies
|
||||||
go.etcd.io/bbolt 2eb7227adea1d5cf85f0bc2a82b7059b13c2fa68
|
|
||||||
google.golang.org/grpc 25c4f928eaa6d96443009bd842389fb4fa48664e # v1.20.1
|
|
||||||
google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944
|
|
||||||
golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4
|
|
||||||
golang.org/x/sys 4c4f7f33c9ed00de01c4c741d2177abfcfe19307 https://github.com/golang/sys
|
|
||||||
golang.org/x/sync 42b317875d0fa942474b76e1b46a6060d720ae6e
|
|
||||||
golang.org/x/net f3200d17e092c607f615320ecaad13d87ad9a2b3
|
|
||||||
github.com/urfave/cli 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c
|
|
||||||
github.com/syndtr/gocapability d98352740cb2c55f81556b63d4a1ec64c5a319c2
|
|
||||||
github.com/sirupsen/logrus v1.4.1
|
|
||||||
github.com/prometheus/procfs cb4147076ac75738c9a7d279075a253c0cc5acbd
|
|
||||||
github.com/prometheus/common 89604d197083d4781071d3c65855d24ecfb0a563
|
|
||||||
github.com/prometheus/client_model 99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c
|
|
||||||
github.com/prometheus/client_golang f4fb1b73fb099f396a7f0036bf86aa8def4ed823
|
|
||||||
github.com/pkg/errors v0.8.1
|
|
||||||
github.com/opencontainers/runtime-spec 29686dbc5559d93fb1ef402eeda3e35c38d75af4 # v1.0.1-59-g29686db
|
|
||||||
github.com/opencontainers/runc f4982d86f7fde0b6f953cc62ccc4022c519a10a9 # v1.0.0-rc8-32-gf4982d86
|
|
||||||
github.com/opencontainers/image-spec v1.0.1
|
|
||||||
github.com/opencontainers/go-digest c9281466c8b2f606084ac71339773efd177436e7
|
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1
|
|
||||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.1
|
|
||||||
github.com/google/uuid v1.1.1
|
|
||||||
github.com/golang/protobuf v1.2.0
|
|
||||||
github.com/gogo/protobuf v1.2.1
|
|
||||||
github.com/gogo/googleapis v1.2.0
|
|
||||||
github.com/godbus/dbus v3
|
|
||||||
github.com/docker/go-units v0.4.0
|
|
||||||
github.com/docker/go-metrics 4ea375f7759c82740c893fc030bc37088d2ec098
|
|
||||||
github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9
|
|
||||||
github.com/coreos/go-systemd v14
|
|
||||||
github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40
|
|
||||||
github.com/containerd/ttrpc 92c8520ef9f86600c650dd540266a007bf03670f
|
|
||||||
github.com/containerd/go-runc e029b79d8cda8374981c64eba71f28ec38e5526f
|
|
||||||
github.com/containerd/fifo bda0ff6ed73c67bfb5e62bc9c697f146b7fd7f13
|
|
||||||
github.com/containerd/continuity f2a389ac0a02ce21c09edd7344677a601970f41c
|
|
||||||
github.com/containerd/containerd d4802a64f9737f02db3426751f380d97fc878dec
|
|
||||||
github.com/containerd/console 0650fd9eeb50bab4fc99dceb9f2e14cf58f36e7f
|
|
||||||
github.com/containerd/cgroups c4b9ac5c7601384c965b9646fc515884e091ebb9
|
|
||||||
github.com/beorn7/perks 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9
|
github.com/beorn7/perks 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9
|
||||||
github.com/Microsoft/hcsshim 9e921883ac929bbe515b39793ece99ce3a9d7706
|
|
||||||
github.com/Microsoft/go-winio v0.4.14
|
|
||||||
github.com/BurntSushi/toml v0.3.1
|
github.com/BurntSushi/toml v0.3.1
|
||||||
|
github.com/containerd/cgroups 9f1c62dddf4bc7cc72822ebe353bae7006141b1b
|
||||||
|
github.com/containerd/console v1.0.0
|
||||||
|
github.com/containerd/containerd v1.3.7
|
||||||
|
github.com/containerd/continuity f2a389ac0a02ce21c09edd7344677a601970f41c
|
||||||
|
github.com/containerd/fifo bda0ff6ed73c67bfb5e62bc9c697f146b7fd7f13
|
||||||
|
github.com/containerd/go-runc e029b79d8cda8374981c64eba71f28ec38e5526f
|
||||||
|
github.com/containerd/ttrpc v1.0.0
|
||||||
|
github.com/containerd/typeurl v1.0.0
|
||||||
|
github.com/coreos/go-systemd v14
|
||||||
|
github.com/cpuguy83/go-md2man v1.0.10
|
||||||
|
github.com/docker/go-events e31b211e4f1cd09aa76fe4ac244571fab96ae47f
|
||||||
|
github.com/docker/go-metrics 4ea375f7759c82740c893fc030bc37088d2ec098
|
||||||
|
github.com/docker/go-units v0.4.0
|
||||||
|
github.com/godbus/dbus v3
|
||||||
|
github.com/gogo/googleapis v1.2.0
|
||||||
|
github.com/gogo/protobuf v1.2.1
|
||||||
|
github.com/golang/protobuf v1.2.0
|
||||||
|
github.com/google/uuid v1.1.1
|
||||||
|
github.com/grpc-ecosystem/go-grpc-prometheus v1.1
|
||||||
|
github.com/hashicorp/errwrap v1.0.0
|
||||||
|
github.com/hashicorp/go-multierror v1.0.0
|
||||||
|
github.com/hashicorp/golang-lru v0.5.3
|
||||||
github.com/imdario/mergo v0.3.7
|
github.com/imdario/mergo v0.3.7
|
||||||
|
github.com/matttproud/golang_protobuf_extensions v1.0.1
|
||||||
|
github.com/Microsoft/go-winio v0.4.14
|
||||||
|
github.com/Microsoft/hcsshim 9e921883ac929bbe515b39793ece99ce3a9d7706
|
||||||
|
github.com/opencontainers/go-digest c9281466c8b2f606084ac71339773efd177436e7
|
||||||
|
github.com/opencontainers/image-spec v1.0.1
|
||||||
|
github.com/opencontainers/runc v1.0.0-rc10
|
||||||
|
github.com/opencontainers/runtime-spec 29686dbc5559d93fb1ef402eeda3e35c38d75af4 # v1.0.1-59-g29686db
|
||||||
|
github.com/pkg/errors v0.8.1
|
||||||
|
github.com/prometheus/client_golang f4fb1b73fb099f396a7f0036bf86aa8def4ed823
|
||||||
|
github.com/prometheus/client_model 99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c
|
||||||
|
github.com/prometheus/common 89604d197083d4781071d3c65855d24ecfb0a563
|
||||||
|
github.com/prometheus/procfs cb4147076ac75738c9a7d279075a253c0cc5acbd
|
||||||
|
github.com/russross/blackfriday v1.5.2
|
||||||
|
github.com/sirupsen/logrus v1.4.1
|
||||||
|
github.com/syndtr/gocapability d98352740cb2c55f81556b63d4a1ec64c5a319c2
|
||||||
|
github.com/urfave/cli v1.22.0
|
||||||
|
go.etcd.io/bbolt v1.3.3
|
||||||
|
go.opencensus.io v0.22.0
|
||||||
|
golang.org/x/net f3200d17e092c607f615320ecaad13d87ad9a2b3
|
||||||
|
golang.org/x/sync 42b317875d0fa942474b76e1b46a6060d720ae6e
|
||||||
|
golang.org/x/sys 9eafafc0a87e0fd0aeeba439a4573537970c44c7
|
||||||
|
golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4
|
||||||
|
google.golang.org/appengine v1.5.0
|
||||||
|
google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944
|
||||||
|
google.golang.org/grpc v1.23.0
|
||||||
|
|
||||||
# kubernetes dependencies
|
# kubernetes dependencies
|
||||||
sigs.k8s.io/yaml v1.1.0
|
|
||||||
k8s.io/utils c2654d5206da6b7b6ace12841e8f359bb89b443c
|
|
||||||
k8s.io/kubernetes v1.16.0-rc.2
|
|
||||||
k8s.io/klog v0.4.0
|
|
||||||
k8s.io/cri-api kubernetes-1.16.0-rc.2
|
|
||||||
k8s.io/client-go kubernetes-1.16.0-rc.2
|
|
||||||
k8s.io/api kubernetes-1.16.0-rc.2
|
|
||||||
k8s.io/apiserver kubernetes-1.16.0-rc.2
|
|
||||||
k8s.io/apimachinery kubernetes-1.16.0-rc.2
|
|
||||||
gopkg.in/yaml.v2 v2.2.2
|
|
||||||
gopkg.in/inf.v0 v0.9.0
|
|
||||||
golang.org/x/time 85acf8d2951cb2a3bde7632f9ff273ef0379bcbd
|
|
||||||
golang.org/x/oauth2 0f29369cfe4552d0e4bcddc57cc75f4d7e672a33
|
|
||||||
golang.org/x/crypto 5c40567a22f818bd14a1ea7245dad9f8ef0691aa
|
|
||||||
github.com/stretchr/testify v1.3.0
|
|
||||||
github.com/seccomp/libseccomp-golang v0.9.1
|
|
||||||
github.com/pmezard/go-difflib v1.0.0
|
|
||||||
github.com/modern-go/reflect2 1.0.1
|
|
||||||
github.com/modern-go/concurrent 1.0.3
|
|
||||||
github.com/json-iterator/go v1.1.7
|
|
||||||
github.com/google/gofuzz v1.0.0
|
|
||||||
github.com/emicklei/go-restful v2.9.5
|
|
||||||
github.com/docker/spdystream 449fdfce4d962303d702fec724ef0ad181c92528
|
|
||||||
github.com/davecgh/go-spew v1.1.1
|
github.com/davecgh/go-spew v1.1.1
|
||||||
|
github.com/docker/spdystream 449fdfce4d962303d702fec724ef0ad181c92528
|
||||||
|
github.com/emicklei/go-restful v2.9.5
|
||||||
|
github.com/google/gofuzz v1.0.0
|
||||||
|
github.com/json-iterator/go v1.1.8
|
||||||
|
github.com/modern-go/concurrent 1.0.3
|
||||||
|
github.com/modern-go/reflect2 v1.0.1
|
||||||
|
github.com/pmezard/go-difflib v1.0.0
|
||||||
|
github.com/stretchr/testify v1.4.0
|
||||||
|
golang.org/x/crypto 60c769a6c58655dab1b9adac0d58967dd517cfba
|
||||||
|
golang.org/x/oauth2 0f29369cfe4552d0e4bcddc57cc75f4d7e672a33
|
||||||
|
golang.org/x/time 9d24e82272b4f38b78bc8cff74fa936d31ccd8ef
|
||||||
|
gopkg.in/inf.v0 v0.9.1
|
||||||
|
gopkg.in/yaml.v2 v2.2.8
|
||||||
|
k8s.io/api v0.16.6
|
||||||
|
k8s.io/apimachinery v0.16.6
|
||||||
|
k8s.io/apiserver v0.16.6
|
||||||
|
k8s.io/client-go v0.16.6
|
||||||
|
k8s.io/cri-api v0.16.6
|
||||||
|
k8s.io/klog v1.0.0
|
||||||
|
k8s.io/kubernetes v1.16.6
|
||||||
|
k8s.io/utils e782cd3c129fc98ee807f3c889c0f26eb7c9daf5
|
||||||
|
sigs.k8s.io/yaml v1.1.0
|
||||||
|
|
||||||
# cni dependencies
|
# cni dependencies
|
||||||
github.com/containernetworking/plugins v0.7.6
|
|
||||||
github.com/containernetworking/cni v0.7.1
|
|
||||||
github.com/containerd/go-cni 49fbd9b210f3c8ee3b7fd3cd797aabaf364627c1
|
github.com/containerd/go-cni 49fbd9b210f3c8ee3b7fd3cd797aabaf364627c1
|
||||||
|
github.com/containernetworking/cni v0.7.1
|
||||||
|
github.com/containernetworking/plugins v0.7.6
|
||||||
|
|
|
@ -0,0 +1,354 @@
|
||||||
|
Mozilla Public License, version 2.0
|
||||||
|
|
||||||
|
1. Definitions
|
||||||
|
|
||||||
|
1.1. “Contributor”
|
||||||
|
|
||||||
|
means each individual or legal entity that creates, contributes to the
|
||||||
|
creation of, or owns Covered Software.
|
||||||
|
|
||||||
|
1.2. “Contributor Version”
|
||||||
|
|
||||||
|
means the combination of the Contributions of others (if any) used by a
|
||||||
|
Contributor and that particular Contributor’s Contribution.
|
||||||
|
|
||||||
|
1.3. “Contribution”
|
||||||
|
|
||||||
|
means Covered Software of a particular Contributor.
|
||||||
|
|
||||||
|
1.4. “Covered Software”
|
||||||
|
|
||||||
|
means Source Code Form to which the initial Contributor has attached the
|
||||||
|
notice in Exhibit A, the Executable Form of such Source Code Form, and
|
||||||
|
Modifications of such Source Code Form, in each case including portions
|
||||||
|
thereof.
|
||||||
|
|
||||||
|
1.5. “Incompatible With Secondary Licenses”
|
||||||
|
means
|
||||||
|
|
||||||
|
a. that the initial Contributor has attached the notice described in
|
||||||
|
Exhibit B to the Covered Software; or
|
||||||
|
|
||||||
|
b. that the Covered Software was made available under the terms of version
|
||||||
|
1.1 or earlier of the License, but not also under the terms of a
|
||||||
|
Secondary License.
|
||||||
|
|
||||||
|
1.6. “Executable Form”
|
||||||
|
|
||||||
|
means any form of the work other than Source Code Form.
|
||||||
|
|
||||||
|
1.7. “Larger Work”
|
||||||
|
|
||||||
|
means a work that combines Covered Software with other material, in a separate
|
||||||
|
file or files, that is not Covered Software.
|
||||||
|
|
||||||
|
1.8. “License”
|
||||||
|
|
||||||
|
means this document.
|
||||||
|
|
||||||
|
1.9. “Licensable”
|
||||||
|
|
||||||
|
means having the right to grant, to the maximum extent possible, whether at the
|
||||||
|
time of the initial grant or subsequently, any and all of the rights conveyed by
|
||||||
|
this License.
|
||||||
|
|
||||||
|
1.10. “Modifications”
|
||||||
|
|
||||||
|
means any of the following:
|
||||||
|
|
||||||
|
a. any file in Source Code Form that results from an addition to, deletion
|
||||||
|
from, or modification of the contents of Covered Software; or
|
||||||
|
|
||||||
|
b. any new file in Source Code Form that contains any Covered Software.
|
||||||
|
|
||||||
|
1.11. “Patent Claims” of a Contributor
|
||||||
|
|
||||||
|
means any patent claim(s), including without limitation, method, process,
|
||||||
|
and apparatus claims, in any patent Licensable by such Contributor that
|
||||||
|
would be infringed, but for the grant of the License, by the making,
|
||||||
|
using, selling, offering for sale, having made, import, or transfer of
|
||||||
|
either its Contributions or its Contributor Version.
|
||||||
|
|
||||||
|
1.12. “Secondary License”
|
||||||
|
|
||||||
|
means either the GNU General Public License, Version 2.0, the GNU Lesser
|
||||||
|
General Public License, Version 2.1, the GNU Affero General Public
|
||||||
|
License, Version 3.0, or any later versions of those licenses.
|
||||||
|
|
||||||
|
1.13. “Source Code Form”
|
||||||
|
|
||||||
|
means the form of the work preferred for making modifications.
|
||||||
|
|
||||||
|
1.14. “You” (or “Your”)
|
||||||
|
|
||||||
|
means an individual or a legal entity exercising rights under this
|
||||||
|
License. For legal entities, “You” includes any entity that controls, is
|
||||||
|
controlled by, or is under common control with You. For purposes of this
|
||||||
|
definition, “control” means (a) the power, direct or indirect, to cause
|
||||||
|
the direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (b) ownership of more than fifty percent (50%) of the
|
||||||
|
outstanding shares or beneficial ownership of such entity.
|
||||||
|
|
||||||
|
|
||||||
|
2. License Grants and Conditions
|
||||||
|
|
||||||
|
2.1. Grants
|
||||||
|
|
||||||
|
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||||
|
non-exclusive license:
|
||||||
|
|
||||||
|
a. under intellectual property rights (other than patent or trademark)
|
||||||
|
Licensable by such Contributor to use, reproduce, make available,
|
||||||
|
modify, display, perform, distribute, and otherwise exploit its
|
||||||
|
Contributions, either on an unmodified basis, with Modifications, or as
|
||||||
|
part of a Larger Work; and
|
||||||
|
|
||||||
|
b. under Patent Claims of such Contributor to make, use, sell, offer for
|
||||||
|
sale, have made, import, and otherwise transfer either its Contributions
|
||||||
|
or its Contributor Version.
|
||||||
|
|
||||||
|
2.2. Effective Date
|
||||||
|
|
||||||
|
The licenses granted in Section 2.1 with respect to any Contribution become
|
||||||
|
effective for each Contribution on the date the Contributor first distributes
|
||||||
|
such Contribution.
|
||||||
|
|
||||||
|
2.3. Limitations on Grant Scope
|
||||||
|
|
||||||
|
The licenses granted in this Section 2 are the only rights granted under this
|
||||||
|
License. No additional rights or licenses will be implied from the distribution
|
||||||
|
or licensing of Covered Software under this License. Notwithstanding Section
|
||||||
|
2.1(b) above, no patent license is granted by a Contributor:
|
||||||
|
|
||||||
|
a. for any code that a Contributor has removed from Covered Software; or
|
||||||
|
|
||||||
|
b. for infringements caused by: (i) Your and any other third party’s
|
||||||
|
modifications of Covered Software, or (ii) the combination of its
|
||||||
|
Contributions with other software (except as part of its Contributor
|
||||||
|
Version); or
|
||||||
|
|
||||||
|
c. under Patent Claims infringed by Covered Software in the absence of its
|
||||||
|
Contributions.
|
||||||
|
|
||||||
|
This License does not grant any rights in the trademarks, service marks, or
|
||||||
|
logos of any Contributor (except as may be necessary to comply with the
|
||||||
|
notice requirements in Section 3.4).
|
||||||
|
|
||||||
|
2.4. Subsequent Licenses
|
||||||
|
|
||||||
|
No Contributor makes additional grants as a result of Your choice to
|
||||||
|
distribute the Covered Software under a subsequent version of this License
|
||||||
|
(see Section 10.2) or under the terms of a Secondary License (if permitted
|
||||||
|
under the terms of Section 3.3).
|
||||||
|
|
||||||
|
2.5. Representation
|
||||||
|
|
||||||
|
Each Contributor represents that the Contributor believes its Contributions
|
||||||
|
are its original creation(s) or it has sufficient rights to grant the
|
||||||
|
rights to its Contributions conveyed by this License.
|
||||||
|
|
||||||
|
2.6. Fair Use
|
||||||
|
|
||||||
|
This License is not intended to limit any rights You have under applicable
|
||||||
|
copyright doctrines of fair use, fair dealing, or other equivalents.
|
||||||
|
|
||||||
|
2.7. Conditions
|
||||||
|
|
||||||
|
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
|
||||||
|
Section 2.1.
|
||||||
|
|
||||||
|
|
||||||
|
3. Responsibilities
|
||||||
|
|
||||||
|
3.1. Distribution of Source Form
|
||||||
|
|
||||||
|
All distribution of Covered Software in Source Code Form, including any
|
||||||
|
Modifications that You create or to which You contribute, must be under the
|
||||||
|
terms of this License. You must inform recipients that the Source Code Form
|
||||||
|
of the Covered Software is governed by the terms of this License, and how
|
||||||
|
they can obtain a copy of this License. You may not attempt to alter or
|
||||||
|
restrict the recipients’ rights in the Source Code Form.
|
||||||
|
|
||||||
|
3.2. Distribution of Executable Form
|
||||||
|
|
||||||
|
If You distribute Covered Software in Executable Form then:
|
||||||
|
|
||||||
|
a. such Covered Software must also be made available in Source Code Form,
|
||||||
|
as described in Section 3.1, and You must inform recipients of the
|
||||||
|
Executable Form how they can obtain a copy of such Source Code Form by
|
||||||
|
reasonable means in a timely manner, at a charge no more than the cost
|
||||||
|
of distribution to the recipient; and
|
||||||
|
|
||||||
|
b. You may distribute such Executable Form under the terms of this License,
|
||||||
|
or sublicense it under different terms, provided that the license for
|
||||||
|
the Executable Form does not attempt to limit or alter the recipients’
|
||||||
|
rights in the Source Code Form under this License.
|
||||||
|
|
||||||
|
3.3. Distribution of a Larger Work
|
||||||
|
|
||||||
|
You may create and distribute a Larger Work under terms of Your choice,
|
||||||
|
provided that You also comply with the requirements of this License for the
|
||||||
|
Covered Software. If the Larger Work is a combination of Covered Software
|
||||||
|
with a work governed by one or more Secondary Licenses, and the Covered
|
||||||
|
Software is not Incompatible With Secondary Licenses, this License permits
|
||||||
|
You to additionally distribute such Covered Software under the terms of
|
||||||
|
such Secondary License(s), so that the recipient of the Larger Work may, at
|
||||||
|
their option, further distribute the Covered Software under the terms of
|
||||||
|
either this License or such Secondary License(s).
|
||||||
|
|
||||||
|
3.4. Notices
|
||||||
|
|
||||||
|
You may not remove or alter the substance of any license notices (including
|
||||||
|
copyright notices, patent notices, disclaimers of warranty, or limitations
|
||||||
|
of liability) contained within the Source Code Form of the Covered
|
||||||
|
Software, except that You may alter any license notices to the extent
|
||||||
|
required to remedy known factual inaccuracies.
|
||||||
|
|
||||||
|
3.5. Application of Additional Terms
|
||||||
|
|
||||||
|
You may choose to offer, and to charge a fee for, warranty, support,
|
||||||
|
indemnity or liability obligations to one or more recipients of Covered
|
||||||
|
Software. However, You may do so only on Your own behalf, and not on behalf
|
||||||
|
of any Contributor. You must make it absolutely clear that any such
|
||||||
|
warranty, support, indemnity, or liability obligation is offered by You
|
||||||
|
alone, and You hereby agree to indemnify every Contributor for any
|
||||||
|
liability incurred by such Contributor as a result of warranty, support,
|
||||||
|
indemnity or liability terms You offer. You may include additional
|
||||||
|
disclaimers of warranty and limitations of liability specific to any
|
||||||
|
jurisdiction.
|
||||||
|
|
||||||
|
4. Inability to Comply Due to Statute or Regulation
|
||||||
|
|
||||||
|
If it is impossible for You to comply with any of the terms of this License
|
||||||
|
with respect to some or all of the Covered Software due to statute, judicial
|
||||||
|
order, or regulation then You must: (a) comply with the terms of this License
|
||||||
|
to the maximum extent possible; and (b) describe the limitations and the code
|
||||||
|
they affect. Such description must be placed in a text file included with all
|
||||||
|
distributions of the Covered Software under this License. Except to the
|
||||||
|
extent prohibited by statute or regulation, such description must be
|
||||||
|
sufficiently detailed for a recipient of ordinary skill to be able to
|
||||||
|
understand it.
|
||||||
|
|
||||||
|
5. Termination
|
||||||
|
|
||||||
|
5.1. The rights granted under this License will terminate automatically if You
|
||||||
|
fail to comply with any of its terms. However, if You become compliant,
|
||||||
|
then the rights granted under this License from a particular Contributor
|
||||||
|
are reinstated (a) provisionally, unless and until such Contributor
|
||||||
|
explicitly and finally terminates Your grants, and (b) on an ongoing basis,
|
||||||
|
if such Contributor fails to notify You of the non-compliance by some
|
||||||
|
reasonable means prior to 60 days after You have come back into compliance.
|
||||||
|
Moreover, Your grants from a particular Contributor are reinstated on an
|
||||||
|
ongoing basis if such Contributor notifies You of the non-compliance by
|
||||||
|
some reasonable means, this is the first time You have received notice of
|
||||||
|
non-compliance with this License from such Contributor, and You become
|
||||||
|
compliant prior to 30 days after Your receipt of the notice.
|
||||||
|
|
||||||
|
5.2. If You initiate litigation against any entity by asserting a patent
|
||||||
|
infringement claim (excluding declaratory judgment actions, counter-claims,
|
||||||
|
and cross-claims) alleging that a Contributor Version directly or
|
||||||
|
indirectly infringes any patent, then the rights granted to You by any and
|
||||||
|
all Contributors for the Covered Software under Section 2.1 of this License
|
||||||
|
shall terminate.
|
||||||
|
|
||||||
|
5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
|
||||||
|
license agreements (excluding distributors and resellers) which have been
|
||||||
|
validly granted by You or Your distributors under this License prior to
|
||||||
|
termination shall survive termination.
|
||||||
|
|
||||||
|
6. Disclaimer of Warranty
|
||||||
|
|
||||||
|
Covered Software is provided under this License on an “as is” basis, without
|
||||||
|
warranty of any kind, either expressed, implied, or statutory, including,
|
||||||
|
without limitation, warranties that the Covered Software is free of defects,
|
||||||
|
merchantable, fit for a particular purpose or non-infringing. The entire
|
||||||
|
risk as to the quality and performance of the Covered Software is with You.
|
||||||
|
Should any Covered Software prove defective in any respect, You (not any
|
||||||
|
Contributor) assume the cost of any necessary servicing, repair, or
|
||||||
|
correction. This disclaimer of warranty constitutes an essential part of this
|
||||||
|
License. No use of any Covered Software is authorized under this License
|
||||||
|
except under this disclaimer.
|
||||||
|
|
||||||
|
7. Limitation of Liability
|
||||||
|
|
||||||
|
Under no circumstances and under no legal theory, whether tort (including
|
||||||
|
negligence), contract, or otherwise, shall any Contributor, or anyone who
|
||||||
|
distributes Covered Software as permitted above, be liable to You for any
|
||||||
|
direct, indirect, special, incidental, or consequential damages of any
|
||||||
|
character including, without limitation, damages for lost profits, loss of
|
||||||
|
goodwill, work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses, even if such party shall have been
|
||||||
|
informed of the possibility of such damages. This limitation of liability
|
||||||
|
shall not apply to liability for death or personal injury resulting from such
|
||||||
|
party’s negligence to the extent applicable law prohibits such limitation.
|
||||||
|
Some jurisdictions do not allow the exclusion or limitation of incidental or
|
||||||
|
consequential damages, so this exclusion and limitation may not apply to You.
|
||||||
|
|
||||||
|
8. Litigation
|
||||||
|
|
||||||
|
Any litigation relating to this License may be brought only in the courts of
|
||||||
|
a jurisdiction where the defendant maintains its principal place of business
|
||||||
|
and such litigation shall be governed by laws of that jurisdiction, without
|
||||||
|
reference to its conflict-of-law provisions. Nothing in this Section shall
|
||||||
|
prevent a party’s ability to bring cross-claims or counter-claims.
|
||||||
|
|
||||||
|
9. Miscellaneous
|
||||||
|
|
||||||
|
This License represents the complete agreement concerning the subject matter
|
||||||
|
hereof. If any provision of this License is held to be unenforceable, such
|
||||||
|
provision shall be reformed only to the extent necessary to make it
|
||||||
|
enforceable. Any law or regulation which provides that the language of a
|
||||||
|
contract shall be construed against the drafter shall not be used to construe
|
||||||
|
this License against a Contributor.
|
||||||
|
|
||||||
|
|
||||||
|
10. Versions of the License
|
||||||
|
|
||||||
|
10.1. New Versions
|
||||||
|
|
||||||
|
Mozilla Foundation is the license steward. Except as provided in Section
|
||||||
|
10.3, no one other than the license steward has the right to modify or
|
||||||
|
publish new versions of this License. Each version will be given a
|
||||||
|
distinguishing version number.
|
||||||
|
|
||||||
|
10.2. Effect of New Versions
|
||||||
|
|
||||||
|
You may distribute the Covered Software under the terms of the version of
|
||||||
|
the License under which You originally received the Covered Software, or
|
||||||
|
under the terms of any subsequent version published by the license
|
||||||
|
steward.
|
||||||
|
|
||||||
|
10.3. Modified Versions
|
||||||
|
|
||||||
|
If you create software not governed by this License, and you want to
|
||||||
|
create a new license for such software, you may create and use a modified
|
||||||
|
version of this License if you rename the license and remove any
|
||||||
|
references to the name of the license steward (except to note that such
|
||||||
|
modified license differs from this License).
|
||||||
|
|
||||||
|
10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses
|
||||||
|
If You choose to distribute Source Code Form that is Incompatible With
|
||||||
|
Secondary Licenses under the terms of this version of the License, the
|
||||||
|
notice described in Exhibit B of this License must be attached.
|
||||||
|
|
||||||
|
Exhibit A - Source Code Form License Notice
|
||||||
|
|
||||||
|
This Source Code Form is subject to the
|
||||||
|
terms of the Mozilla Public License, v.
|
||||||
|
2.0. If a copy of the MPL was not
|
||||||
|
distributed with this file, You can
|
||||||
|
obtain one at
|
||||||
|
http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
If it is not possible or desirable to put the notice in a particular file, then
|
||||||
|
You may include the notice in a location (such as a LICENSE file in a relevant
|
||||||
|
directory) where a recipient would be likely to look for such a notice.
|
||||||
|
|
||||||
|
You may add additional accurate notices of copyright ownership.
|
||||||
|
|
||||||
|
Exhibit B - “Incompatible With Secondary Licenses” Notice
|
||||||
|
|
||||||
|
This Source Code Form is “Incompatible
|
||||||
|
With Secondary Licenses”, as defined by
|
||||||
|
the Mozilla Public License, v. 2.0.
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
# errwrap
|
||||||
|
|
||||||
|
`errwrap` is a package for Go that formalizes the pattern of wrapping errors
|
||||||
|
and checking if an error contains another error.
|
||||||
|
|
||||||
|
There is a common pattern in Go of taking a returned `error` value and
|
||||||
|
then wrapping it (such as with `fmt.Errorf`) before returning it. The problem
|
||||||
|
with this pattern is that you completely lose the original `error` structure.
|
||||||
|
|
||||||
|
Arguably the _correct_ approach is that you should make a custom structure
|
||||||
|
implementing the `error` interface, and have the original error as a field
|
||||||
|
on that structure, such [as this example](http://golang.org/pkg/os/#PathError).
|
||||||
|
This is a good approach, but you have to know the entire chain of possible
|
||||||
|
rewrapping that happens, when you might just care about one.
|
||||||
|
|
||||||
|
`errwrap` formalizes this pattern (it doesn't matter what approach you use
|
||||||
|
above) by giving a single interface for wrapping errors, checking if a specific
|
||||||
|
error is wrapped, and extracting that error.
|
||||||
|
|
||||||
|
## Installation and Docs
|
||||||
|
|
||||||
|
Install using `go get github.com/hashicorp/errwrap`.
|
||||||
|
|
||||||
|
Full documentation is available at
|
||||||
|
http://godoc.org/github.com/hashicorp/errwrap
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
#### Basic Usage
|
||||||
|
|
||||||
|
Below is a very basic example of its usage:
|
||||||
|
|
||||||
|
```go
|
||||||
|
// A function that always returns an error, but wraps it, like a real
|
||||||
|
// function might.
|
||||||
|
func tryOpen() error {
|
||||||
|
_, err := os.Open("/i/dont/exist")
|
||||||
|
if err != nil {
|
||||||
|
return errwrap.Wrapf("Doesn't exist: {{err}}", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
err := tryOpen()
|
||||||
|
|
||||||
|
// We can use the Contains helpers to check if an error contains
|
||||||
|
// another error. It is safe to do this with a nil error, or with
|
||||||
|
// an error that doesn't even use the errwrap package.
|
||||||
|
if errwrap.Contains(err, ErrNotExist) {
|
||||||
|
// Do something
|
||||||
|
}
|
||||||
|
if errwrap.ContainsType(err, new(os.PathError)) {
|
||||||
|
// Do something
|
||||||
|
}
|
||||||
|
|
||||||
|
// Or we can use the associated `Get` functions to just extract
|
||||||
|
// a specific error. This would return nil if that specific error doesn't
|
||||||
|
// exist.
|
||||||
|
perr := errwrap.GetType(err, new(os.PathError))
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Custom Types
|
||||||
|
|
||||||
|
If you're already making custom types that properly wrap errors, then
|
||||||
|
you can get all the functionality of `errwraps.Contains` and such by
|
||||||
|
implementing the `Wrapper` interface with just one function. Example:
|
||||||
|
|
||||||
|
```go
|
||||||
|
type AppError {
|
||||||
|
Code ErrorCode
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *AppError) WrappedErrors() []error {
|
||||||
|
return []error{e.Err}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Now this works:
|
||||||
|
|
||||||
|
```go
|
||||||
|
err := &AppError{Err: fmt.Errorf("an error")}
|
||||||
|
if errwrap.ContainsType(err, fmt.Errorf("")) {
|
||||||
|
// This will work!
|
||||||
|
}
|
||||||
|
```
|
|
@ -0,0 +1,169 @@
|
||||||
|
// Package errwrap implements methods to formalize error wrapping in Go.
|
||||||
|
//
|
||||||
|
// All of the top-level functions that take an `error` are built to be able
|
||||||
|
// to take any error, not just wrapped errors. This allows you to use errwrap
|
||||||
|
// without having to type-check and type-cast everywhere.
|
||||||
|
package errwrap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// WalkFunc is the callback called for Walk.
|
||||||
|
type WalkFunc func(error)
|
||||||
|
|
||||||
|
// Wrapper is an interface that can be implemented by custom types to
|
||||||
|
// have all the Contains, Get, etc. functions in errwrap work.
|
||||||
|
//
|
||||||
|
// When Walk reaches a Wrapper, it will call the callback for every
|
||||||
|
// wrapped error in addition to the wrapper itself. Since all the top-level
|
||||||
|
// functions in errwrap use Walk, this means that all those functions work
|
||||||
|
// with your custom type.
|
||||||
|
type Wrapper interface {
|
||||||
|
WrappedErrors() []error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wrap defines that outer wraps inner, returning an error type that
|
||||||
|
// can be cleanly used with the other methods in this package, such as
|
||||||
|
// Contains, GetAll, etc.
|
||||||
|
//
|
||||||
|
// This function won't modify the error message at all (the outer message
|
||||||
|
// will be used).
|
||||||
|
func Wrap(outer, inner error) error {
|
||||||
|
return &wrappedError{
|
||||||
|
Outer: outer,
|
||||||
|
Inner: inner,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wrapf wraps an error with a formatting message. This is similar to using
|
||||||
|
// `fmt.Errorf` to wrap an error. If you're using `fmt.Errorf` to wrap
|
||||||
|
// errors, you should replace it with this.
|
||||||
|
//
|
||||||
|
// format is the format of the error message. The string '{{err}}' will
|
||||||
|
// be replaced with the original error message.
|
||||||
|
func Wrapf(format string, err error) error {
|
||||||
|
outerMsg := "<nil>"
|
||||||
|
if err != nil {
|
||||||
|
outerMsg = err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
outer := errors.New(strings.Replace(
|
||||||
|
format, "{{err}}", outerMsg, -1))
|
||||||
|
|
||||||
|
return Wrap(outer, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contains checks if the given error contains an error with the
|
||||||
|
// message msg. If err is not a wrapped error, this will always return
|
||||||
|
// false unless the error itself happens to match this msg.
|
||||||
|
func Contains(err error, msg string) bool {
|
||||||
|
return len(GetAll(err, msg)) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// ContainsType checks if the given error contains an error with
|
||||||
|
// the same concrete type as v. If err is not a wrapped error, this will
|
||||||
|
// check the err itself.
|
||||||
|
func ContainsType(err error, v interface{}) bool {
|
||||||
|
return len(GetAllType(err, v)) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get is the same as GetAll but returns the deepest matching error.
|
||||||
|
func Get(err error, msg string) error {
|
||||||
|
es := GetAll(err, msg)
|
||||||
|
if len(es) > 0 {
|
||||||
|
return es[len(es)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetType is the same as GetAllType but returns the deepest matching error.
|
||||||
|
func GetType(err error, v interface{}) error {
|
||||||
|
es := GetAllType(err, v)
|
||||||
|
if len(es) > 0 {
|
||||||
|
return es[len(es)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAll gets all the errors that might be wrapped in err with the
|
||||||
|
// given message. The order of the errors is such that the outermost
|
||||||
|
// matching error (the most recent wrap) is index zero, and so on.
|
||||||
|
func GetAll(err error, msg string) []error {
|
||||||
|
var result []error
|
||||||
|
|
||||||
|
Walk(err, func(err error) {
|
||||||
|
if err.Error() == msg {
|
||||||
|
result = append(result, err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAllType gets all the errors that are the same type as v.
|
||||||
|
//
|
||||||
|
// The order of the return value is the same as described in GetAll.
|
||||||
|
func GetAllType(err error, v interface{}) []error {
|
||||||
|
var result []error
|
||||||
|
|
||||||
|
var search string
|
||||||
|
if v != nil {
|
||||||
|
search = reflect.TypeOf(v).String()
|
||||||
|
}
|
||||||
|
Walk(err, func(err error) {
|
||||||
|
var needle string
|
||||||
|
if err != nil {
|
||||||
|
needle = reflect.TypeOf(err).String()
|
||||||
|
}
|
||||||
|
|
||||||
|
if needle == search {
|
||||||
|
result = append(result, err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// Walk walks all the wrapped errors in err and calls the callback. If
|
||||||
|
// err isn't a wrapped error, this will be called once for err. If err
|
||||||
|
// is a wrapped error, the callback will be called for both the wrapper
|
||||||
|
// that implements error as well as the wrapped error itself.
|
||||||
|
func Walk(err error, cb WalkFunc) {
|
||||||
|
if err == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch e := err.(type) {
|
||||||
|
case *wrappedError:
|
||||||
|
cb(e.Outer)
|
||||||
|
Walk(e.Inner, cb)
|
||||||
|
case Wrapper:
|
||||||
|
cb(err)
|
||||||
|
|
||||||
|
for _, err := range e.WrappedErrors() {
|
||||||
|
Walk(err, cb)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
cb(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// wrappedError is an implementation of error that has both the
|
||||||
|
// outer and inner errors.
|
||||||
|
type wrappedError struct {
|
||||||
|
Outer error
|
||||||
|
Inner error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *wrappedError) Error() string {
|
||||||
|
return w.Outer.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *wrappedError) WrappedErrors() []error {
|
||||||
|
return []error{w.Outer, w.Inner}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
sudo: false
|
||||||
|
|
||||||
|
language: go
|
||||||
|
|
||||||
|
go:
|
||||||
|
- 1.6
|
||||||
|
|
||||||
|
branches:
|
||||||
|
only:
|
||||||
|
- master
|
||||||
|
|
||||||
|
script: make test testrace
|
|
@ -0,0 +1,353 @@
|
||||||
|
Mozilla Public License, version 2.0
|
||||||
|
|
||||||
|
1. Definitions
|
||||||
|
|
||||||
|
1.1. “Contributor”
|
||||||
|
|
||||||
|
means each individual or legal entity that creates, contributes to the
|
||||||
|
creation of, or owns Covered Software.
|
||||||
|
|
||||||
|
1.2. “Contributor Version”
|
||||||
|
|
||||||
|
means the combination of the Contributions of others (if any) used by a
|
||||||
|
Contributor and that particular Contributor’s Contribution.
|
||||||
|
|
||||||
|
1.3. “Contribution”
|
||||||
|
|
||||||
|
means Covered Software of a particular Contributor.
|
||||||
|
|
||||||
|
1.4. “Covered Software”
|
||||||
|
|
||||||
|
means Source Code Form to which the initial Contributor has attached the
|
||||||
|
notice in Exhibit A, the Executable Form of such Source Code Form, and
|
||||||
|
Modifications of such Source Code Form, in each case including portions
|
||||||
|
thereof.
|
||||||
|
|
||||||
|
1.5. “Incompatible With Secondary Licenses”
|
||||||
|
means
|
||||||
|
|
||||||
|
a. that the initial Contributor has attached the notice described in
|
||||||
|
Exhibit B to the Covered Software; or
|
||||||
|
|
||||||
|
b. that the Covered Software was made available under the terms of version
|
||||||
|
1.1 or earlier of the License, but not also under the terms of a
|
||||||
|
Secondary License.
|
||||||
|
|
||||||
|
1.6. “Executable Form”
|
||||||
|
|
||||||
|
means any form of the work other than Source Code Form.
|
||||||
|
|
||||||
|
1.7. “Larger Work”
|
||||||
|
|
||||||
|
means a work that combines Covered Software with other material, in a separate
|
||||||
|
file or files, that is not Covered Software.
|
||||||
|
|
||||||
|
1.8. “License”
|
||||||
|
|
||||||
|
means this document.
|
||||||
|
|
||||||
|
1.9. “Licensable”
|
||||||
|
|
||||||
|
means having the right to grant, to the maximum extent possible, whether at the
|
||||||
|
time of the initial grant or subsequently, any and all of the rights conveyed by
|
||||||
|
this License.
|
||||||
|
|
||||||
|
1.10. “Modifications”
|
||||||
|
|
||||||
|
means any of the following:
|
||||||
|
|
||||||
|
a. any file in Source Code Form that results from an addition to, deletion
|
||||||
|
from, or modification of the contents of Covered Software; or
|
||||||
|
|
||||||
|
b. any new file in Source Code Form that contains any Covered Software.
|
||||||
|
|
||||||
|
1.11. “Patent Claims” of a Contributor
|
||||||
|
|
||||||
|
means any patent claim(s), including without limitation, method, process,
|
||||||
|
and apparatus claims, in any patent Licensable by such Contributor that
|
||||||
|
would be infringed, but for the grant of the License, by the making,
|
||||||
|
using, selling, offering for sale, having made, import, or transfer of
|
||||||
|
either its Contributions or its Contributor Version.
|
||||||
|
|
||||||
|
1.12. “Secondary License”
|
||||||
|
|
||||||
|
means either the GNU General Public License, Version 2.0, the GNU Lesser
|
||||||
|
General Public License, Version 2.1, the GNU Affero General Public
|
||||||
|
License, Version 3.0, or any later versions of those licenses.
|
||||||
|
|
||||||
|
1.13. “Source Code Form”
|
||||||
|
|
||||||
|
means the form of the work preferred for making modifications.
|
||||||
|
|
||||||
|
1.14. “You” (or “Your”)
|
||||||
|
|
||||||
|
means an individual or a legal entity exercising rights under this
|
||||||
|
License. For legal entities, “You” includes any entity that controls, is
|
||||||
|
controlled by, or is under common control with You. For purposes of this
|
||||||
|
definition, “control” means (a) the power, direct or indirect, to cause
|
||||||
|
the direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (b) ownership of more than fifty percent (50%) of the
|
||||||
|
outstanding shares or beneficial ownership of such entity.
|
||||||
|
|
||||||
|
|
||||||
|
2. License Grants and Conditions
|
||||||
|
|
||||||
|
2.1. Grants
|
||||||
|
|
||||||
|
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||||
|
non-exclusive license:
|
||||||
|
|
||||||
|
a. under intellectual property rights (other than patent or trademark)
|
||||||
|
Licensable by such Contributor to use, reproduce, make available,
|
||||||
|
modify, display, perform, distribute, and otherwise exploit its
|
||||||
|
Contributions, either on an unmodified basis, with Modifications, or as
|
||||||
|
part of a Larger Work; and
|
||||||
|
|
||||||
|
b. under Patent Claims of such Contributor to make, use, sell, offer for
|
||||||
|
sale, have made, import, and otherwise transfer either its Contributions
|
||||||
|
or its Contributor Version.
|
||||||
|
|
||||||
|
2.2. Effective Date
|
||||||
|
|
||||||
|
The licenses granted in Section 2.1 with respect to any Contribution become
|
||||||
|
effective for each Contribution on the date the Contributor first distributes
|
||||||
|
such Contribution.
|
||||||
|
|
||||||
|
2.3. Limitations on Grant Scope
|
||||||
|
|
||||||
|
The licenses granted in this Section 2 are the only rights granted under this
|
||||||
|
License. No additional rights or licenses will be implied from the distribution
|
||||||
|
or licensing of Covered Software under this License. Notwithstanding Section
|
||||||
|
2.1(b) above, no patent license is granted by a Contributor:
|
||||||
|
|
||||||
|
a. for any code that a Contributor has removed from Covered Software; or
|
||||||
|
|
||||||
|
b. for infringements caused by: (i) Your and any other third party’s
|
||||||
|
modifications of Covered Software, or (ii) the combination of its
|
||||||
|
Contributions with other software (except as part of its Contributor
|
||||||
|
Version); or
|
||||||
|
|
||||||
|
c. under Patent Claims infringed by Covered Software in the absence of its
|
||||||
|
Contributions.
|
||||||
|
|
||||||
|
This License does not grant any rights in the trademarks, service marks, or
|
||||||
|
logos of any Contributor (except as may be necessary to comply with the
|
||||||
|
notice requirements in Section 3.4).
|
||||||
|
|
||||||
|
2.4. Subsequent Licenses
|
||||||
|
|
||||||
|
No Contributor makes additional grants as a result of Your choice to
|
||||||
|
distribute the Covered Software under a subsequent version of this License
|
||||||
|
(see Section 10.2) or under the terms of a Secondary License (if permitted
|
||||||
|
under the terms of Section 3.3).
|
||||||
|
|
||||||
|
2.5. Representation
|
||||||
|
|
||||||
|
Each Contributor represents that the Contributor believes its Contributions
|
||||||
|
are its original creation(s) or it has sufficient rights to grant the
|
||||||
|
rights to its Contributions conveyed by this License.
|
||||||
|
|
||||||
|
2.6. Fair Use
|
||||||
|
|
||||||
|
This License is not intended to limit any rights You have under applicable
|
||||||
|
copyright doctrines of fair use, fair dealing, or other equivalents.
|
||||||
|
|
||||||
|
2.7. Conditions
|
||||||
|
|
||||||
|
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
|
||||||
|
Section 2.1.
|
||||||
|
|
||||||
|
|
||||||
|
3. Responsibilities
|
||||||
|
|
||||||
|
3.1. Distribution of Source Form
|
||||||
|
|
||||||
|
All distribution of Covered Software in Source Code Form, including any
|
||||||
|
Modifications that You create or to which You contribute, must be under the
|
||||||
|
terms of this License. You must inform recipients that the Source Code Form
|
||||||
|
of the Covered Software is governed by the terms of this License, and how
|
||||||
|
they can obtain a copy of this License. You may not attempt to alter or
|
||||||
|
restrict the recipients’ rights in the Source Code Form.
|
||||||
|
|
||||||
|
3.2. Distribution of Executable Form
|
||||||
|
|
||||||
|
If You distribute Covered Software in Executable Form then:
|
||||||
|
|
||||||
|
a. such Covered Software must also be made available in Source Code Form,
|
||||||
|
as described in Section 3.1, and You must inform recipients of the
|
||||||
|
Executable Form how they can obtain a copy of such Source Code Form by
|
||||||
|
reasonable means in a timely manner, at a charge no more than the cost
|
||||||
|
of distribution to the recipient; and
|
||||||
|
|
||||||
|
b. You may distribute such Executable Form under the terms of this License,
|
||||||
|
or sublicense it under different terms, provided that the license for
|
||||||
|
the Executable Form does not attempt to limit or alter the recipients’
|
||||||
|
rights in the Source Code Form under this License.
|
||||||
|
|
||||||
|
3.3. Distribution of a Larger Work
|
||||||
|
|
||||||
|
You may create and distribute a Larger Work under terms of Your choice,
|
||||||
|
provided that You also comply with the requirements of this License for the
|
||||||
|
Covered Software. If the Larger Work is a combination of Covered Software
|
||||||
|
with a work governed by one or more Secondary Licenses, and the Covered
|
||||||
|
Software is not Incompatible With Secondary Licenses, this License permits
|
||||||
|
You to additionally distribute such Covered Software under the terms of
|
||||||
|
such Secondary License(s), so that the recipient of the Larger Work may, at
|
||||||
|
their option, further distribute the Covered Software under the terms of
|
||||||
|
either this License or such Secondary License(s).
|
||||||
|
|
||||||
|
3.4. Notices
|
||||||
|
|
||||||
|
You may not remove or alter the substance of any license notices (including
|
||||||
|
copyright notices, patent notices, disclaimers of warranty, or limitations
|
||||||
|
of liability) contained within the Source Code Form of the Covered
|
||||||
|
Software, except that You may alter any license notices to the extent
|
||||||
|
required to remedy known factual inaccuracies.
|
||||||
|
|
||||||
|
3.5. Application of Additional Terms
|
||||||
|
|
||||||
|
You may choose to offer, and to charge a fee for, warranty, support,
|
||||||
|
indemnity or liability obligations to one or more recipients of Covered
|
||||||
|
Software. However, You may do so only on Your own behalf, and not on behalf
|
||||||
|
of any Contributor. You must make it absolutely clear that any such
|
||||||
|
warranty, support, indemnity, or liability obligation is offered by You
|
||||||
|
alone, and You hereby agree to indemnify every Contributor for any
|
||||||
|
liability incurred by such Contributor as a result of warranty, support,
|
||||||
|
indemnity or liability terms You offer. You may include additional
|
||||||
|
disclaimers of warranty and limitations of liability specific to any
|
||||||
|
jurisdiction.
|
||||||
|
|
||||||
|
4. Inability to Comply Due to Statute or Regulation
|
||||||
|
|
||||||
|
If it is impossible for You to comply with any of the terms of this License
|
||||||
|
with respect to some or all of the Covered Software due to statute, judicial
|
||||||
|
order, or regulation then You must: (a) comply with the terms of this License
|
||||||
|
to the maximum extent possible; and (b) describe the limitations and the code
|
||||||
|
they affect. Such description must be placed in a text file included with all
|
||||||
|
distributions of the Covered Software under this License. Except to the
|
||||||
|
extent prohibited by statute or regulation, such description must be
|
||||||
|
sufficiently detailed for a recipient of ordinary skill to be able to
|
||||||
|
understand it.
|
||||||
|
|
||||||
|
5. Termination
|
||||||
|
|
||||||
|
5.1. The rights granted under this License will terminate automatically if You
|
||||||
|
fail to comply with any of its terms. However, if You become compliant,
|
||||||
|
then the rights granted under this License from a particular Contributor
|
||||||
|
are reinstated (a) provisionally, unless and until such Contributor
|
||||||
|
explicitly and finally terminates Your grants, and (b) on an ongoing basis,
|
||||||
|
if such Contributor fails to notify You of the non-compliance by some
|
||||||
|
reasonable means prior to 60 days after You have come back into compliance.
|
||||||
|
Moreover, Your grants from a particular Contributor are reinstated on an
|
||||||
|
ongoing basis if such Contributor notifies You of the non-compliance by
|
||||||
|
some reasonable means, this is the first time You have received notice of
|
||||||
|
non-compliance with this License from such Contributor, and You become
|
||||||
|
compliant prior to 30 days after Your receipt of the notice.
|
||||||
|
|
||||||
|
5.2. If You initiate litigation against any entity by asserting a patent
|
||||||
|
infringement claim (excluding declaratory judgment actions, counter-claims,
|
||||||
|
and cross-claims) alleging that a Contributor Version directly or
|
||||||
|
indirectly infringes any patent, then the rights granted to You by any and
|
||||||
|
all Contributors for the Covered Software under Section 2.1 of this License
|
||||||
|
shall terminate.
|
||||||
|
|
||||||
|
5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
|
||||||
|
license agreements (excluding distributors and resellers) which have been
|
||||||
|
validly granted by You or Your distributors under this License prior to
|
||||||
|
termination shall survive termination.
|
||||||
|
|
||||||
|
6. Disclaimer of Warranty
|
||||||
|
|
||||||
|
Covered Software is provided under this License on an “as is” basis, without
|
||||||
|
warranty of any kind, either expressed, implied, or statutory, including,
|
||||||
|
without limitation, warranties that the Covered Software is free of defects,
|
||||||
|
merchantable, fit for a particular purpose or non-infringing. The entire
|
||||||
|
risk as to the quality and performance of the Covered Software is with You.
|
||||||
|
Should any Covered Software prove defective in any respect, You (not any
|
||||||
|
Contributor) assume the cost of any necessary servicing, repair, or
|
||||||
|
correction. This disclaimer of warranty constitutes an essential part of this
|
||||||
|
License. No use of any Covered Software is authorized under this License
|
||||||
|
except under this disclaimer.
|
||||||
|
|
||||||
|
7. Limitation of Liability
|
||||||
|
|
||||||
|
Under no circumstances and under no legal theory, whether tort (including
|
||||||
|
negligence), contract, or otherwise, shall any Contributor, or anyone who
|
||||||
|
distributes Covered Software as permitted above, be liable to You for any
|
||||||
|
direct, indirect, special, incidental, or consequential damages of any
|
||||||
|
character including, without limitation, damages for lost profits, loss of
|
||||||
|
goodwill, work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses, even if such party shall have been
|
||||||
|
informed of the possibility of such damages. This limitation of liability
|
||||||
|
shall not apply to liability for death or personal injury resulting from such
|
||||||
|
party’s negligence to the extent applicable law prohibits such limitation.
|
||||||
|
Some jurisdictions do not allow the exclusion or limitation of incidental or
|
||||||
|
consequential damages, so this exclusion and limitation may not apply to You.
|
||||||
|
|
||||||
|
8. Litigation
|
||||||
|
|
||||||
|
Any litigation relating to this License may be brought only in the courts of
|
||||||
|
a jurisdiction where the defendant maintains its principal place of business
|
||||||
|
and such litigation shall be governed by laws of that jurisdiction, without
|
||||||
|
reference to its conflict-of-law provisions. Nothing in this Section shall
|
||||||
|
prevent a party’s ability to bring cross-claims or counter-claims.
|
||||||
|
|
||||||
|
9. Miscellaneous
|
||||||
|
|
||||||
|
This License represents the complete agreement concerning the subject matter
|
||||||
|
hereof. If any provision of this License is held to be unenforceable, such
|
||||||
|
provision shall be reformed only to the extent necessary to make it
|
||||||
|
enforceable. Any law or regulation which provides that the language of a
|
||||||
|
contract shall be construed against the drafter shall not be used to construe
|
||||||
|
this License against a Contributor.
|
||||||
|
|
||||||
|
|
||||||
|
10. Versions of the License
|
||||||
|
|
||||||
|
10.1. New Versions
|
||||||
|
|
||||||
|
Mozilla Foundation is the license steward. Except as provided in Section
|
||||||
|
10.3, no one other than the license steward has the right to modify or
|
||||||
|
publish new versions of this License. Each version will be given a
|
||||||
|
distinguishing version number.
|
||||||
|
|
||||||
|
10.2. Effect of New Versions
|
||||||
|
|
||||||
|
You may distribute the Covered Software under the terms of the version of
|
||||||
|
the License under which You originally received the Covered Software, or
|
||||||
|
under the terms of any subsequent version published by the license
|
||||||
|
steward.
|
||||||
|
|
||||||
|
10.3. Modified Versions
|
||||||
|
|
||||||
|
If you create software not governed by this License, and you want to
|
||||||
|
create a new license for such software, you may create and use a modified
|
||||||
|
version of this License if you rename the license and remove any
|
||||||
|
references to the name of the license steward (except to note that such
|
||||||
|
modified license differs from this License).
|
||||||
|
|
||||||
|
10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses
|
||||||
|
If You choose to distribute Source Code Form that is Incompatible With
|
||||||
|
Secondary Licenses under the terms of this version of the License, the
|
||||||
|
notice described in Exhibit B of this License must be attached.
|
||||||
|
|
||||||
|
Exhibit A - Source Code Form License Notice
|
||||||
|
|
||||||
|
This Source Code Form is subject to the
|
||||||
|
terms of the Mozilla Public License, v.
|
||||||
|
2.0. If a copy of the MPL was not
|
||||||
|
distributed with this file, You can
|
||||||
|
obtain one at
|
||||||
|
http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
If it is not possible or desirable to put the notice in a particular file, then
|
||||||
|
You may include the notice in a location (such as a LICENSE file in a relevant
|
||||||
|
directory) where a recipient would be likely to look for such a notice.
|
||||||
|
|
||||||
|
You may add additional accurate notices of copyright ownership.
|
||||||
|
|
||||||
|
Exhibit B - “Incompatible With Secondary Licenses” Notice
|
||||||
|
|
||||||
|
This Source Code Form is “Incompatible
|
||||||
|
With Secondary Licenses”, as defined by
|
||||||
|
the Mozilla Public License, v. 2.0.
|
|
@ -0,0 +1,31 @@
|
||||||
|
TEST?=./...
|
||||||
|
|
||||||
|
default: test
|
||||||
|
|
||||||
|
# test runs the test suite and vets the code.
|
||||||
|
test: generate
|
||||||
|
@echo "==> Running tests..."
|
||||||
|
@go list $(TEST) \
|
||||||
|
| grep -v "/vendor/" \
|
||||||
|
| xargs -n1 go test -timeout=60s -parallel=10 ${TESTARGS}
|
||||||
|
|
||||||
|
# testrace runs the race checker
|
||||||
|
testrace: generate
|
||||||
|
@echo "==> Running tests (race)..."
|
||||||
|
@go list $(TEST) \
|
||||||
|
| grep -v "/vendor/" \
|
||||||
|
| xargs -n1 go test -timeout=60s -race ${TESTARGS}
|
||||||
|
|
||||||
|
# updatedeps installs all the dependencies needed to run and build.
|
||||||
|
updatedeps:
|
||||||
|
@sh -c "'${CURDIR}/scripts/deps.sh' '${NAME}'"
|
||||||
|
|
||||||
|
# generate runs `go generate` to build the dynamically generated source files.
|
||||||
|
generate:
|
||||||
|
@echo "==> Generating..."
|
||||||
|
@find . -type f -name '.DS_Store' -delete
|
||||||
|
@go list ./... \
|
||||||
|
| grep -v "/vendor/" \
|
||||||
|
| xargs -n1 go generate
|
||||||
|
|
||||||
|
.PHONY: default test testrace updatedeps generate
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue