[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
Jacob Blain Christen 2021-03-17 14:34:38 -07:00 committed by GitHub
parent 790b740f01
commit 31fddb21b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
107 changed files with 3184 additions and 662 deletions

View File

@ -1,7 +1,7 @@
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 \
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 && \
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 && \

4
go.mod
View File

@ -8,9 +8,9 @@ replace (
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/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/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/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

10
go.sum
View File

@ -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.11.2 h1:bUDfHRK8aKGdya+msYJHffDwNxB8Eileyl7Jf2qqYjI=
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/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-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=
@ -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/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/rancher/containerd v1.3.0-k3s.5 h1:r5GheXz59KQpEdYPxRd53vfFhipnQG/g3MI5NkNPDQI=
github.com/rancher/containerd v1.3.0-k3s.5/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.2/go.mod h1:Ht5T1dIKzm+4NExmb7wDVG6qR+j0xeXIjjhCv1d9geY=
github.com/rancher/containerd v1.3.10-k3s1 h1:PXYxupAyWAeNneHp6Xz77RIVV5sQQZkcBz1jNtv5HZE=
github.com/rancher/containerd v1.3.10-k3s1/go.mod h1:ZMfzmqce2Z+QSEqdHMfeJs1TZ/UeJ1aDrazjpQT4ehM=
github.com/rancher/cri v1.3.0-k3s.10 h1:JPHitKhHThVM2qEgyZOjl2m88EDGeN90eEelqg0Sv7I=
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/go.mod h1:TEKhKv2EJIZp+p9jnEy4C63g8CosJzsI4kyKKkHag+8=
github.com/rancher/dynamiclistener v0.2.0 h1:KucYwJXVVGhZ/NndfMCeQoCafT/VN7kvqSGgmlX8Lxk=

View File

@ -18,6 +18,6 @@ done
mkdir -p bin/aux && rm bin/mount && ln -sf ../busybox bin/aux/mount
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/

View File

@ -7,12 +7,13 @@ clone_folder: c:\gopath\src\github.com\containerd\containerd
branches:
only:
- master
- /release\/.*/
environment:
GOPATH: C:\gopath
CGO_ENABLED: 1
matrix:
- GO_VERSION: 1.12.12
- GO_VERSION: 1.13.12
before_build:
- choco install -y mingw --version 5.3.0

View File

@ -15,7 +15,7 @@ linters:
- errcheck
run:
deadline: 2m
deadline: 3m
skip-dirs:
- api
- design

View File

@ -1,38 +1,77 @@
Abhinandan Prativadi <abhi@docker.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.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>
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>
Cao Zhihao <caozhihao@163.com>
Cao Zhihao <caozhihao@163.com> <caozhihao.xd@bytedance.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>
Fahed Dorgaa <fahed.dorgaa@gmail.com>
Frank Yang <yyb196@gmail.com>
Fupan Li <lifupan@gmail.com>
Georgia Panoutsakopoulou <gpanoutsak@gmail.com>
Guangming Wang <guangming.wang@daocloud.io>
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> <liaojian@Dabllo.local>
Ji'an Liu <anthonyliu@zju.edu.cn>
Jie Zhang <iamkadisi@163.com>
John Howard <john.howard@microsoft.com> <jhoward@microsoft.com>
John Howard <john.howard@microsoft.com> <jhowardmsft@users.noreply.github.com>
John Howard <github@lowenna.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>
Justin Cormack <justin.cormack@docker.com> <justin@specialbusservice.com>
Justin Terry <juterry@microsoft.com>
Justin Terry <juterry@microsoft.com> <jterry75@users.noreply.github.com>
Kenfe-Mickaël Laventure <mickael.laventure@gmail.com>
Kevin Kern <kaiwentan@harmonycloud.cn>
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>
Lifubang <lifubang@aliyun.com> <lifubang@acmcoder.com>
Lu Jingxiao <lujingxiao@huawei.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>
Michael Katsoulis <michaelkatsoulis88@gmail.com>
Mike Brown <brownwm@us.ibm.com> <mikebrow@users.noreply.github.com>
Nishchay Kumar <mrawesomenix@gmail.com>
Oliver Stenbom <oliver@stenbom.eu> <ostenbom@pivotal.io>
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>
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> <stevvooe@users.noreply.github.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>
Xiaodong Zhang <a4012017@sina.com>
Xuean Yan <yan.xuean@zte.com.cn>
Yue Zhang <zy675793960@yeah.net>
Yuxing Liu <starnop@163.com>
zhenguang zhu <zhengguang.zhu@daocloud.io>
zhongming chang<zhongming.chang@daocloud.io>
zhoulin xie <zhoulin.xie@daocloud.io>
zhoulin xie <zhoulin.xie@daocloud.io> <42261994+JoeWrightss@users.noreply.github.com>
Zhang Wei <zhangwei555@huawei.com>
Zhenguang Zhu <zhengguang.zhu@daocloud.io>
Zhiyu Li <payall4u@qq.com> <404977848@qq.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>

View File

@ -4,19 +4,24 @@ sudo: required
services:
- docker
branches:
except:
- master
- release/1.3
language: go
os:
- linux
go:
- "1.12.12"
- "1.13.15"
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.v2 TRAVIS_CGO_ENABLED=1 TRAVIS_DISTRO=bionic
- TRAVIS_GOOS=linux TEST_RUNTIME=io.containerd.runtime.v1.linux TRAVIS_CGO_ENABLED=1 TRAVIS_DISTRO=bionic
- TRAVIS_GOOS=darwin TRAVIS_CGO_ENABLED=0
- 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_RELEASE=yes GOPROXY=direct
- 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 GOPROXY=direct
matrix:
include:
@ -24,7 +29,7 @@ matrix:
- if: type != pull_request
os: linux
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
@ -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-cni ; 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 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
before_script:
@ -73,7 +78,7 @@ script:
- DCO_VERBOSITY=-q ../project/script/validate/dco
- ../project/script/validate/fileheader ../project/
- 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 .
- make check
- 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 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 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
- 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
sudo mkdir -p /etc/containerd
@ -107,8 +112,7 @@ after_success:
- bash <(curl -s https://codecov.io/bash) -F linux
before_deploy:
- make release
- if [ "$TRAVIS_GOOS" = "linux" ]; then make cri-release; fi
- if [ "$TRAVIS_RELEASE" = "yes" ]; then make release cri-release; fi
deploy:
- provider: releases

View File

@ -207,7 +207,7 @@ Next, let's build `runc`:
```sh
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!

View File

@ -80,9 +80,14 @@ TEST_REQUIRES_ROOT_PACKAGES=$(filter \
done | sort -u) \
)
ifdef SKIPTESTS
PACKAGES:=$(filter-out ${SKIPTESTS},${PACKAGES})
TEST_REQUIRES_ROOT_PACKAGES:=$(filter-out ${SKIPTESTS},${TEST_REQUIRES_ROOT_PACKAGES})
endif
# Project binaries.
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
GO_BUILDTAGS = ${BUILDTAGS}
@ -111,7 +116,7 @@ GO_GCFLAGS=$(shell \
BINARIES=$(addprefix bin/,$(COMMANDS))
# Flags passed to `go test`
TESTFLAGS ?= $(TESTFLAGS_RACE)
TESTFLAGS ?= $(TESTFLAGS_RACE) $(EXTRA_TESTFLAGS)
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
@ -204,15 +209,15 @@ mandir:
@mkdir -p man
# 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) $@"
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) $@"
go run cmd/gen-manpages/main.go ctr man/
go run cmd/gen-manpages/main.go $(@F) $(@D)
man/%: docs/man/%.md FORCE
@echo "$(WHALE) $@"

View File

@ -52,6 +52,6 @@ containerd is designed to be embedded into a larger system, hence it only includ
### 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.
For the scope of this project to change it requires a 100% vote from all maintainers of the project.

View File

@ -71,7 +71,7 @@ var (
func init() {
flag.BoolVar(&debugFlag, "debug", false, "enable debug output in logs")
flag.StringVar(&namespaceFlag, "namespace", "", "namespace that owns the shim")
flag.StringVar(&socketFlag, "socket", "", "abstract socket path to serve")
flag.StringVar(&socketFlag, "socket", "", "socket path to serve")
flag.StringVar(&addressFlag, "address", "", "grpc address back to main containerd")
flag.StringVar(&workdirFlag, "workdir", "", "path used to storge large temporary data")
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()
path = "[inherited from parent]"
} else {
if len(path) > 106 {
return errors.Errorf("%q: unix socket path too long (> 106)", path)
const (
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 {
return err

View File

@ -227,6 +227,10 @@ can be used and modified as necessary as a custom configuration.`
}
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())
<-done
return nil

View File

@ -52,6 +52,10 @@ func handleSignals(ctx context.Context, signals chan os.Signal, serverC chan *se
case unix.SIGPIPE:
continue
default:
if err := notifyStopping(ctx); err != nil {
log.G(ctx).WithError(err).Error("notify stopping failed")
}
if server == nil {
close(done)
return

View File

@ -51,6 +51,11 @@ func handleSignals(ctx context.Context, signals chan os.Signal, serverC chan *se
server = s
case s := <-signals:
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 {
close(done)
return

View 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
}

View 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
}

View File

@ -42,16 +42,17 @@ var (
registerServiceFlag bool
unregisterServiceFlag bool
runServiceFlag bool
logFileFlag string
kernel32 = windows.NewLazySystemDLL("kernel32.dll")
setStdHandle = kernel32.NewProc("SetStdHandle")
allocConsole = kernel32.NewProc("AllocConsole")
oldStderr windows.Handle
panicFile *os.File
service *handler
)
const defaultServiceName = "containerd"
// serviceFlags returns an array of flags for configuring containerd to run
// as a Windows service under control of SCM.
func serviceFlags() []cli.Flag {
@ -59,7 +60,7 @@ func serviceFlags() []cli.Flag {
cli.StringFlag{
Name: "service-name",
Usage: "Set the Windows service name",
Value: "containerd",
Value: defaultServiceName,
},
cli.BoolFlag{
Name: "register-service",
@ -74,14 +75,18 @@ func serviceFlags() []cli.Flag {
Usage: "",
Hidden: true,
},
cli.StringFlag{
Name: "log-file",
Usage: "Path to the containerd log file",
},
}
}
// applyPlatformFlags applies platform-specific flags.
func applyPlatformFlags(context *cli.Context) {
if s := context.GlobalString("service-name"); s != "" {
serviceNameFlag = s
serviceNameFlag = context.GlobalString("service-name")
if serviceNameFlag == "" {
serviceNameFlag = defaultServiceName
}
for _, v := range []struct {
name string
@ -102,6 +107,7 @@ func applyPlatformFlags(context *cli.Context) {
} {
*v.d = context.GlobalBool(v.name)
}
logFileFlag = context.GlobalString("log-file")
}
type handler struct {
@ -243,7 +249,15 @@ func registerUnregisterService(root string) (bool, error) {
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
}
@ -266,7 +280,6 @@ func launchService(s *server.Server, done chan struct{}) error {
return err
}
service = h
go func() {
if interactive {
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
// it when it panics. Remember the old stderr to restore it before removing
// the panic file.
sh := windows.STD_ERROR_HANDLE
h, err := windows.GetStdHandle(uint32(sh))
sh := uint32(windows.STD_ERROR_HANDLE)
h, err := windows.GetStdHandle(sh)
if err != nil {
return err
}
@ -359,7 +372,7 @@ func initPanicFile(path string) error {
func removePanicFile() {
if st, err := panicFile.Stat(); err == nil {
if st.Size() == 0 {
sh := windows.STD_ERROR_HANDLE
sh := uint32(windows.STD_ERROR_HANDLE)
setStdHandle.Call(uintptr(sh), uintptr(oldStderr))
panicFile.Close()
os.Remove(panicFile.Name())

View File

@ -24,6 +24,7 @@ import (
"io/ioutil"
"net"
"path/filepath"
"strings"
"github.com/containerd/console"
"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")
// this should not error, ctr always get a default 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} {
conn, err := net.Dial("unix", "\x00"+socket)
for _, socket := range []string{s2, "\x00" + s1} {
conn, err := net.Dial("unix", socket)
if err == nil {
client := ttrpc.NewClient(conn)

View File

@ -23,6 +23,7 @@ import (
"syscall"
"github.com/containerd/containerd"
"github.com/containerd/containerd/errdefs"
"github.com/sirupsen/logrus"
)
@ -36,8 +37,16 @@ func ForwardAllSignals(ctx gocontext.Context, task killer) chan os.Signal {
signal.Notify(sigc)
go func() {
for s := range sigc {
if canIgnoreSignal(s) {
logrus.Debugf("Ignoring signal %s", s)
continue
}
logrus.Debug("forwarding signal ", s)
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)
}
}

View 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
}

View 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
}

1
vendor/github.com/containerd/containerd/codecov.yml generated vendored Normal file
View File

@ -0,0 +1 @@
comment: false

View File

@ -32,10 +32,12 @@ import (
"github.com/containerd/containerd/images"
"github.com/containerd/containerd/oci"
"github.com/containerd/containerd/runtime/v2/runc/options"
"github.com/containerd/containerd/sys"
"github.com/containerd/typeurl"
prototypes "github.com/gogo/protobuf/types"
ver "github.com/opencontainers/image-spec/specs-go"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/opencontainers/selinux/go-selinux/label"
"github.com/pkg/errors"
)
@ -242,7 +244,17 @@ func (c *container) NewTask(ctx context.Context, ioCreate cio.Creator, opts ...N
if err != nil {
return nil, err
}
spec, err := c.Spec(ctx)
if err != nil {
return nil, err
}
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{
Type: m.Type,
Source: m.Source,
@ -411,14 +423,33 @@ func attachExistingIO(response *tasks.GetResponse, ioAttach cio.Attach) (cio.IO,
// loadFifos loads the containers fifos
func loadFifos(response *tasks.GetResponse) *cio.FIFOSet {
path := getFifoDir([]string{
fifos := []string{
response.Process.Stdin,
response.Process.Stdout,
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{
Stdin: response.Process.Stdin,
Stdout: response.Process.Stdout,
@ -426,14 +457,3 @@ func loadFifos(response *tasks.GetResponse) *cio.FIFOSet {
Terminal: response.Process.Terminal,
}, 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 ""
}

View File

@ -87,21 +87,21 @@ func WithRestoreRuntime(ctx context.Context, id string, client *Client, checkpoi
return err
}
}
var options *ptypes.Any
var options ptypes.Any
if m != nil {
store := client.ContentStore()
data, err := content.ReadBlob(ctx, store, *m)
if err != nil {
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
}
}
c.Runtime = containers.RuntimeInfo{
Name: name,
Options: options,
Options: &options,
}
return nil
}

View File

@ -7,9 +7,11 @@ After=network.target local-fs.target
ExecStartPre=-/sbin/modprobe overlay
ExecStart=/usr/local/bin/containerd
Type=notify
Delegate=yes
KillMode=process
Restart=always
RestartSec=5
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNPROC=infinity
@ -18,6 +20,7 @@ LimitNOFILE=1048576
# Comment TasksMax if your systemd version does not supports it.
# Only systemd 226 and above support this version.
TasksMax=infinity
OOMScoreAdjust=-999
[Install]
WantedBy=multi-user.target

View File

@ -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 {
syscalls := []specs.LinuxSyscall{
{
@ -55,7 +55,7 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
"accept",
"accept4",
"access",
"alarm",
"adjtimex",
"alarm",
"bind",
"brk",
@ -65,9 +65,14 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
"chmod",
"chown",
"chown32",
"clock_adjtime",
"clock_adjtime64",
"clock_getres",
"clock_getres_time64",
"clock_gettime",
"clock_gettime64",
"clock_nanosleep",
"clock_nanosleep_time64",
"close",
"connect",
"copy_file_range",
@ -89,6 +94,7 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
"exit",
"exit_group",
"faccessat",
"faccessat2",
"fadvise64",
"fadvise64_64",
"fallocate",
@ -117,6 +123,7 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
"ftruncate",
"ftruncate64",
"futex",
"futex_time64",
"futimesat",
"getcpu",
"getcwd",
@ -163,10 +170,14 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
"io_destroy",
"io_getevents",
"io_pgetevents",
"io_pgetevents_time64",
"ioprio_get",
"ioprio_set",
"io_setup",
"io_submit",
"io_uring_enter",
"io_uring_register",
"io_uring_setup",
"ipc",
"kill",
"lchown",
@ -184,6 +195,7 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
"lstat",
"lstat64",
"madvise",
"membarrier",
"memfd_create",
"mincore",
"mkdir",
@ -200,7 +212,9 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
"mq_notify",
"mq_open",
"mq_timedreceive",
"mq_timedreceive_time64",
"mq_timedsend",
"mq_timedsend_time64",
"mq_unlink",
"mremap",
"msgctl",
@ -216,18 +230,23 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
"_newselect",
"open",
"openat",
"openat2",
"pause",
"pipe",
"pipe2",
"poll",
"ppoll",
"ppoll_time64",
"prctl",
"pread64",
"preadv",
"preadv2",
"prlimit64",
"pselect6",
"pselect6_time64",
"pwrite64",
"pwritev",
"pwritev2",
"read",
"readahead",
"readlink",
@ -236,6 +255,7 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
"recv",
"recvfrom",
"recvmmsg",
"recvmmsg_time64",
"recvmsg",
"remap_file_pages",
"removexattr",
@ -244,6 +264,7 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
"renameat2",
"restart_syscall",
"rmdir",
"rseq",
"rt_sigaction",
"rt_sigpending",
"rt_sigprocmask",
@ -251,6 +272,7 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
"rt_sigreturn",
"rt_sigsuspend",
"rt_sigtimedwait",
"rt_sigtimedwait_time64",
"rt_tgsigqueueinfo",
"sched_getaffinity",
"sched_getattr",
@ -259,6 +281,7 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
"sched_get_priority_min",
"sched_getscheduler",
"sched_rr_get_interval",
"sched_rr_get_interval_time64",
"sched_setaffinity",
"sched_setattr",
"sched_setparam",
@ -270,6 +293,7 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
"semget",
"semop",
"semtimedop",
"semtimedop_time64",
"send",
"sendfile",
"sendfile64",
@ -329,18 +353,21 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
"sync_file_range",
"syncfs",
"sysinfo",
"syslog",
"tee",
"tgkill",
"time",
"timer_create",
"timer_delete",
"timerfd_create",
"timerfd_gettime",
"timerfd_settime",
"timer_getoverrun",
"timer_gettime",
"timer_gettime64",
"timer_settime",
"timer_settime64",
"timerfd_create",
"timerfd_gettime",
"timerfd_gettime64",
"timerfd_settime",
"timerfd_settime64",
"times",
"tkill",
"truncate",
@ -352,6 +379,7 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
"unlinkat",
"utime",
"utimensat",
"utimensat_time64",
"utimes",
"vfork",
"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"},
Action: specs.ActAllow,
@ -407,11 +457,20 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
// include by arch
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":
s.Syscalls = append(s.Syscalls, specs.LinuxSyscall{
Names: []string{
"arm_fadvise64_64",
"arm_sync_file_range",
"sync_file_range2",
"breakpoint",
"cacheflush",
"set_tls",
@ -468,9 +527,11 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
"mount",
"name_to_handle_at",
"perf_event_open",
"quotactl",
"setdomainname",
"sethostname",
"setns",
"syslog",
"umount",
"umount2",
"unshare",
@ -496,7 +557,6 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
"delete_module",
"init_module",
"finit_module",
"query_module",
},
Action: specs.ActAllow,
Args: []specs.LinuxSeccompArg{},
@ -532,7 +592,7 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
Names: []string{
"settimeofday",
"stime",
"adjtimex",
"clock_settime",
},
Action: specs.ActAllow,
Args: []specs.LinuxSeccompArg{},
@ -543,6 +603,12 @@ func DefaultProfile(sp *specs.Spec) *specs.LinuxSeccomp {
Action: specs.ActAllow,
Args: []specs.LinuxSeccompArg{},
})
case "CAP_SYSLOG":
s.Syscalls = append(s.Syscalls, specs.LinuxSyscall{
Names: []string{"syslog"},
Action: specs.ActAllow,
Args: []specs.LinuxSeccompArg{},
})
}
}

View File

@ -20,7 +20,7 @@ package seccomp
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 {
return &specs.LinuxSeccomp{}
}

View File

@ -209,6 +209,8 @@ func (p *parser) field() (string, error) {
return s, nil
case tokenQuoted:
return p.unquote(pos, s, false)
case tokenIllegal:
return "", p.mkerr(pos, p.scanner.err)
}
return "", p.mkerr(pos, "expected field or quoted")
@ -228,6 +230,8 @@ func (p *parser) operator() (operator, error) {
default:
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 ("=="|"!="|"~=")`)
@ -241,6 +245,8 @@ func (p *parser) value(allowAltQuotes bool) (string, error) {
return s, nil
case tokenQuoted:
return p.unquote(pos, s, allowAltQuotes)
case tokenIllegal:
return "", p.mkerr(pos, p.scanner.err)
}
return "", p.mkerr(pos, "expected value or quoted")

View File

@ -17,7 +17,6 @@
package filters
import (
"fmt"
"unicode"
"unicode/utf8"
)
@ -64,6 +63,7 @@ type scanner struct {
pos int
ppos int // bounds the current rune in the string
value bool
err string
}
func (s *scanner) init(input string) {
@ -82,12 +82,14 @@ func (s *scanner) next() rune {
s.ppos += w
if r == utf8.RuneError {
if w > 0 {
s.error("rune error")
return tokenIllegal
}
return tokenEOF
}
if r == 0 {
s.error("unexpected null")
return tokenIllegal
}
@ -114,7 +116,9 @@ chomp:
case ch == tokenEOF:
case ch == tokenIllegal:
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]
case isSeparatorRune(ch):
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
for ch != quote {
if ch == '\n' || ch < 0 {
s.error("literal not terminated")
return
s.error("quoted literal not terminated")
return false
}
if ch == '\\' {
ch = s.scanEscape(quote)
var legal bool
ch, legal = s.scanEscape(quote)
if !legal {
illegal = true
}
} else {
ch = s.next()
}
}
return !illegal
}
func (s *scanner) scanEscape(quote rune) rune {
ch := s.next() // read character after '/'
func (s *scanner) scanEscape(quote rune) (ch rune, legal bool) {
ch = s.next() // read character after '/'
switch ch {
case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', quote:
// nothing to do
ch = s.next()
legal = true
case '0', '1', '2', '3', '4', '5', '6', '7':
ch = s.scanDigits(ch, 8, 3)
ch, legal = s.scanDigits(ch, 8, 3)
case 'x':
ch = s.scanDigits(s.next(), 16, 2)
ch, legal = s.scanDigits(s.next(), 16, 2)
case 'u':
ch = s.scanDigits(s.next(), 16, 4)
ch, legal = s.scanDigits(s.next(), 16, 4)
case 'U':
ch = s.scanDigits(s.next(), 16, 8)
ch, legal = s.scanDigits(s.next(), 16, 8)
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 {
ch = s.next()
n--
}
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) {
fmt.Println("error fixme", msg)
if s.err == "" {
s.err = msg
}
}
func digitVal(ch rune) int {

View File

@ -197,24 +197,26 @@ func (i *image) Usage(ctx context.Context, opts ...UsageOpt) (int64, error) {
desc.Size = info.Size
}
for k, v := range info.Labels {
const prefix = "containerd.io/gc.ref.snapshot."
if !strings.HasPrefix(k, prefix) {
continue
}
sn := i.client.SnapshotService(k[len(prefix):])
if sn == nil {
continue
}
u, err := sn.Usage(ctx, v)
if err != nil {
if !errdefs.IsNotFound(err) && !errdefs.IsInvalidArgument(err) {
return nil, err
if config.snapshots {
for k, v := range info.Labels {
const prefix = "containerd.io/gc.ref.snapshot."
if !strings.HasPrefix(k, prefix) {
continue
}
sn := i.client.SnapshotService(k[len(prefix):])
if sn == nil {
continue
}
u, err := sn.Usage(ctx, v)
if err != nil {
if !errdefs.IsNotFound(err) && !errdefs.IsInvalidArgument(err) {
return nil, err
}
} else {
usage += u.Size
}
} else {
usage += u.Size
}
}
}

View File

@ -181,7 +181,7 @@ func ImportIndex(ctx context.Context, store content.Store, reader io.Reader, opt
Layers: layers,
}
desc, err := writeManifest(ctx, store, manifest, ocispec.MediaTypeImageManifest)
desc, err := writeManifest(ctx, store, manifest, manifest.MediaType)
if err != nil {
return ocispec.Descriptor{}, errors.Wrap(err, "write docker manifest")
}

View File

@ -21,6 +21,8 @@ import (
"context"
"os"
"path/filepath"
"runtime"
"strings"
introspectionapi "github.com/containerd/containerd/api/services/introspection/v1"
"github.com/containerd/containerd/archive"
@ -48,6 +50,15 @@ func (c *Client) Install(ctx context.Context, image Image, opts ...InstallOpts)
if err != nil {
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 {
ra, err := cs.ReaderAt(ctx, layer)
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) {
d := filepath.Dir(hdr.Name)
result := d == "bin"
result := d == binDir
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 _, err := os.Lstat(filepath.Join(path, hdr.Name)); err == nil {

View File

@ -69,3 +69,7 @@ func (s *deletedState) SetExited(status int) {
func (s *deletedState) Exec(ctx context.Context, path string, r *ExecConfig) (Process, error) {
return nil, errors.Errorf("cannot exec in a deleted state")
}
func (s *deletedState) Status(ctx context.Context) (string, error) {
return "stopped", nil
}

View File

@ -96,7 +96,6 @@ func (e *execProcess) setExited(status int) {
e.status = status
e.exited = time.Now()
e.parent.Platform.ShutdownConsole(context.Background(), e.console)
e.pid.set(StoppedPID)
close(e.waitBlock)
}
@ -147,7 +146,7 @@ func (e *execProcess) kill(ctx context.Context, sig uint32, _ bool) error {
switch {
case pid == 0:
return errors.Wrap(errdefs.ErrFailedPrecondition, "process not created")
case pid < 0:
case !e.exited.IsZero():
return errors.Wrapf(errdefs.ErrNotFound, "process already finished")
default:
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()
defer e.mu.Unlock()
// if we don't have a pid(pid=0) then the exec process has just been created
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
return e.execState.Status(ctx)
}

View File

@ -31,6 +31,7 @@ type execState interface {
Delete(context.Context) error
Kill(context.Context, uint32, bool) error
SetExited(int)
Status(context.Context) (string, error)
}
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 {
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 {
p *execProcess
}
@ -157,3 +166,7 @@ func (s *execStoppedState) Kill(ctx context.Context, sig uint32, all bool) error
func (s *execStoppedState) SetExited(status int) {
// no op
}
func (s *execStoppedState) Status(ctx context.Context) (string, error) {
return "stopped", nil
}

View File

@ -56,15 +56,17 @@ type Init struct {
WorkDir string
id string
Bundle string
console console.Console
Platform stdio.Platform
io *processIO
runtime *runc.Runc
id string
Bundle string
console console.Console
Platform stdio.Platform
io *processIO
runtime *runc.Runc
// pausing preserves the pausing state.
pausing *atomicBool
status int
exited time.Time
pid safePid
pid int
closers []io.Closer
stdin io.Closer
stdio stdio.Stdio
@ -97,6 +99,7 @@ func New(id string, runtime *runc.Runc, stdio stdio.Stdio) *Init {
p := &Init{
id: id,
runtime: runtime,
pausing: new(atomicBool),
stdio: stdio,
status: 0,
waitBlock: make(chan struct{}),
@ -113,8 +116,6 @@ func (p *Init) Create(ctx context.Context, r *CreateConfig) error {
pio *processIO
pidFile = newPidFile(p.Bundle)
)
p.pid.Lock()
defer p.pid.Unlock()
if r.Terminal {
if socket, err = runc.NewTempConsoleSocket(); err != nil {
@ -170,7 +171,7 @@ func (p *Init) Create(ctx context.Context, r *CreateConfig) error {
if err != nil {
return errors.Wrap(err, "failed to retrieve OCI runtime container pid")
}
p.pid.pid = pid
p.pid = pid
return nil
}
@ -216,7 +217,7 @@ func (p *Init) ID() string {
// Pid of the process
func (p *Init) Pid() int {
return p.pid.get()
return p.pid
}
// ExitStatus of the process
@ -237,17 +238,14 @@ func (p *Init) ExitedAt() time.Time {
// Status of the process
func (p *Init) Status(ctx context.Context) (string, error) {
if p.pausing.get() {
return "pausing", nil
}
p.mu.Lock()
defer p.mu.Unlock()
c, err := p.runtime.State(ctx, p.id)
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
return p.initState.Status(ctx)
}
// Start the init process
@ -275,7 +273,6 @@ func (p *Init) setExited(status int) {
p.exited = time.Now()
p.status = status
p.Platform.ShutdownConsole(context.Background(), p.console)
p.pid.set(StoppedPID)
close(p.waitBlock)
}

View File

@ -37,6 +37,7 @@ type initState interface {
Exec(context.Context, string, *ExecConfig) (Process, error)
Kill(context.Context, uint32, bool) error
SetExited(int)
Status(context.Context) (string, error)
}
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)
}
func (s *createdState) Status(ctx context.Context) (string, error) {
return "created", nil
}
type createdCheckpointState struct {
p *Init
opts *runc.RestoreOpts
@ -142,9 +147,6 @@ func (s *createdCheckpointState) Start(ctx context.Context) error {
p := s.p
sio := p.stdio
p.pid.Lock()
defer p.pid.Unlock()
var (
err error
socket *runc.Socket
@ -184,7 +186,7 @@ func (s *createdCheckpointState) Start(ctx context.Context) error {
if err != nil {
return errors.Wrap(err, "failed to retrieve OCI runtime container pid")
}
p.pid.pid = pid
p.pid = pid
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")
}
func (s *createdCheckpointState) Status(ctx context.Context) (string, error) {
return "created", nil
}
type runningState struct {
p *Init
}
@ -228,6 +234,13 @@ func (s *runningState) transition(name string) 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 {
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)
}
func (s *runningState) Status(ctx context.Context) (string, error) {
return "running", nil
}
type pausedState struct {
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")
}
func (s *pausedState) Status(ctx context.Context) (string, error) {
return "paused", nil
}
type stoppedState struct {
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) {
return nil, errors.Errorf("cannot exec in a stopped state")
}
func (s *stoppedState) Status(ctx context.Context) (string, error) {
return "stopped", nil
}

View File

@ -29,15 +29,20 @@ import (
"sync"
"sync/atomic"
"syscall"
"time"
"github.com/containerd/containerd/log"
"github.com/containerd/containerd/namespaces"
"github.com/containerd/containerd/pkg/stdio"
"github.com/containerd/containerd/sys"
"github.com/containerd/fifo"
runc "github.com/containerd/go-runc"
"github.com/hashicorp/go-multierror"
"github.com/pkg/errors"
)
const binaryIOProcTermTimeout = 12 * time.Second // Give logger process solid 10 seconds for cleanup
var bufPool = sync.Pool{
New: func() interface{} {
// 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 {
return err
}
@ -240,28 +245,13 @@ func (c *countingWriteCloser) Close() error {
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
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)
if err != nil {
return nil, err
}
var args []string
for k, vs := range uri.Query() {
args = append(args, k)
@ -269,86 +259,146 @@ func NewBinaryIO(ctx context.Context, id string, uri *url.URL) (runc.IO, error)
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,
"CONTAINER_ID="+id,
"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)
// don't need to register this with the reaper or wait when
// running inside a shim
if err := cmd.Start(); err != nil {
cancel()
return nil, err
return nil, errors.Wrap(err, "failed to start binary process")
}
closers = append(closers, func() error { return cmd.Process.Kill() })
// close our side of the pipe after start
if err := w.Close(); err != nil {
cancel()
return nil, err
return nil, errors.Wrap(err, "failed to close write pipe after start")
}
// wait for the logging binary to be ready
b := make([]byte, 1)
if _, err := r.Read(b); err != nil && err != io.EOF {
cancel()
return nil, err
return nil, errors.Wrap(err, "failed to read from logging binary")
}
return &binaryIO{
cmd: cmd,
cancel: cancel,
out: out,
err: serr,
cmd: cmd,
out: out,
err: serr,
}, nil
}
type binaryIO struct {
cmd *exec.Cmd
cancel func()
out, err *pipe
}
func (b *binaryIO) CloseAfterStart() (err error) {
for _, v := range []*pipe{
b.out,
b.err,
} {
func (b *binaryIO) CloseAfterStart() error {
var (
result *multierror.Error
)
for _, v := range []*pipe{b.out, b.err} {
if v != nil {
if cerr := v.r.Close(); err == nil {
err = cerr
if err := v.r.Close(); err != nil {
result = multierror.Append(result, err)
}
}
}
return err
return result.ErrorOrNil()
}
func (b *binaryIO) Close() (err error) {
b.cancel()
for _, v := range []*pipe{
b.out,
b.err,
} {
func (b *binaryIO) Close() error {
var (
result *multierror.Error
)
for _, v := range []*pipe{b.out, b.err} {
if v != nil {
if cerr := v.Close(); err == nil {
err = cerr
if err := v.Close(); err != nil {
result = multierror.Append(result, err)
}
}
}
return 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
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 {
@ -389,9 +439,15 @@ type pipe struct {
}
func (p *pipe) Close() error {
err := p.w.Close()
if rerr := p.r.Close(); err == nil {
err = rerr
var result *multierror.Error
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:")
}

View File

@ -27,6 +27,7 @@ import (
"path/filepath"
"strings"
"sync"
"sync/atomic"
"time"
"github.com/containerd/containerd/errdefs"
@ -38,8 +39,6 @@ import (
const (
// RuncRoot is the path to the root runc state directory
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 = "init.pid"
)
@ -56,10 +55,18 @@ func (s *safePid) get() int {
return s.pid
}
func (s *safePid) set(pid int) {
s.Lock()
s.pid = pid
s.Unlock()
type atomicBool int32
func (ab *atomicBool) set(b bool) {
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?
@ -130,6 +137,8 @@ func checkKillError(err error) error {
strings.Contains(strings.ToLower(err.Error()), "no such process") ||
err == unix.ESRCH {
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")
}

View File

@ -189,9 +189,8 @@ func Parse(specifier string) (specs.Platform, error) {
if isKnownOS(p.OS) {
// picks a default architecture
p.Architecture = runtime.GOARCH
if p.Architecture == "arm" {
// TODO(stevvooe): Resolve arm variant, if not v6 (default)
return specs.Platform{}, errors.Wrapf(errdefs.ErrNotImplemented, "arm support not fully implemented")
if p.Architecture == "arm" && cpuVariant != "v7" {
p.Variant = cpuVariant
}
return p, nil

View File

@ -70,6 +70,11 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (_ Ima
}
unpackWrapper, eg := u.handlerWrapper(ctx, &unpacks)
defer func() {
if retErr != nil {
// Forcibly stop the unpacker if there is
// an error.
eg.Cancel()
}
if err := eg.Wait(); err != nil {
if retErr == nil {
retErr = errors.Wrap(err, "unpack")

View File

@ -96,41 +96,49 @@ func (r dockerFetcher) Fetch(ctx context.Context, desc ocispec.Descriptor) (io.R
images.MediaTypeDockerSchema1Manifest,
ocispec.MediaTypeImageManifest, ocispec.MediaTypeImageIndex:
var firstErr error
for _, host := range r.hosts {
req := r.request(host, http.MethodGet, "manifests", desc.Digest.String())
rc, err := r.open(ctx, req, desc.MediaType, offset)
if err != nil {
if errdefs.IsNotFound(err) {
continue // try another host
// Store the error for referencing later
if firstErr == nil {
firstErr = err
}
return nil, err
continue // try another host
}
return rc, nil
}
return nil, firstErr
}
// Finally use blobs endpoints
var firstErr error
for _, host := range r.hosts {
req := r.request(host, http.MethodGet, "blobs", desc.Digest.String())
rc, err := r.open(ctx, req, desc.MediaType, offset)
if err != nil {
if errdefs.IsNotFound(err) {
continue // try another host
// Store the error for referencing later
if firstErr == nil {
firstErr = err
}
return nil, err
continue // try another host
}
return rc, nil
}
return nil, errors.Wrapf(errdefs.ErrNotFound,
"could not fetch content descriptor %v (%v) from remote",
desc.Digest, desc.MediaType)
if errdefs.IsNotFound(firstErr) {
firstErr = errors.Wrapf(errdefs.ErrNotFound,
"could not fetch content descriptor %v (%v) from remote",
desc.Digest, desc.MediaType)
}
return nil, firstErr
})
}

View File

@ -204,6 +204,7 @@ func (p dockerPusher) Push(ctx context.Context, desc ocispec.Descriptor) (conten
q.Add("digest", desc.Digest.String())
req = p.request(lhost, http.MethodPut)
req.header.Set("Content-Type", "application/octet-stream")
req.path = lurl.Path + "?" + q.Encode()
}
p.tracker.SetStatus(ref, Status{

View File

@ -286,7 +286,11 @@ func (r *dockerResolver) Resolve(ctx context.Context, ref string) (string, ocisp
if errors.Cause(err) == ErrInvalidAuthorization {
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.

View File

@ -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) {
config := b.shimConfig(ns, c, ropts)
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
func (b *bundle) Delete() error {
address, _ := b.loadAddress()
if address != "" {
// we don't care about errors here
client.RemoveSocket(address)
}
err := atomicDelete(b.path)
if err == nil {
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")
}
func (b *bundle) shimAddress(namespace string) string {
d := sha256.Sum256([]byte(filepath.Join(namespace, b.id)))
return filepath.Join(string(filepath.Separator), "containerd-shim", fmt.Sprintf("%x.sock", d))
const socketRoot = "/run/containerd"
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) {

View File

@ -62,6 +62,9 @@ const (
configFilename = "config.json"
defaultRuntime = "runc"
defaultShim = "containerd-shim"
// cleanupTimeout is default timeout for cleanup operations
cleanupTimeout = 1 * time.Minute
)
func init() {
@ -212,7 +215,10 @@ func (r *Runtime) Create(ctx context.Context, id string, opts runtime.CreateOpts
}
defer func() {
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")
}
}

View File

@ -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) {
socket, err := newSocket(address)
if err != nil {
return nil, nil, err
if !eaddrinuse(err) {
return nil, nil, err
}
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
}
}
defer socket.Close()
f, err := socket.File()
if err != nil {
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 {
stderrLog.Close()
}
socket.Close()
RemoveSocket(address)
}()
log.G(ctx).WithFields(logrus.Fields{
"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
// to ensure a shim has a lower* score than the daemons
// if not already at the maximum OOM Score
func setupOOMScore(shimPid int) error {
pid := os.Getpid()
score, err := sys.GetOOMScoreAdj(pid)
@ -147,6 +178,9 @@ func setupOOMScore(shimPid int) error {
return errors.Wrap(err, "get daemon OOM score")
}
shimScore := score + 1
if shimScore > sys.OOMScoreAdjMax {
shimScore = sys.OOMScoreAdjMax
}
if err := sys.SetOOMScore(shimPid, shimScore); err != nil {
return errors.Wrap(err, "set shim OOM score")
}
@ -210,31 +244,73 @@ func writeFile(path, address string) error {
return os.Rename(tempPath, path)
}
func newSocket(address string) (*net.UnixListener, error) {
if len(address) > 106 {
return nil, errors.Errorf("%q: unix socket path too long (> 106)", address)
const (
abstractSocketPrefix = "\x00"
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 {
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
}
// 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) {
return d(address, 100*time.Second)
}
func annonDialer(address string, timeout time.Duration) (net.Conn, error) {
address = strings.TrimPrefix(address, "unix://")
return net.DialTimeout("unix", "\x00"+address, timeout)
func anonDialer(address string, timeout time.Duration) (net.Conn, error) {
return net.DialTimeout("unix", socket(address).path(), timeout)
}
// WithConnect connects to an existing shim
func WithConnect(address string, onClose func()) Opt {
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 {
return nil, nil, err
}
@ -323,21 +399,31 @@ func (c *Client) signalShim(ctx context.Context, sig syscall.Signal) error {
select {
case <-ctx.Done():
return ctx.Err()
case <-c.waitForExit(pid):
case <-c.waitForExit(ctx, pid):
return nil
}
}
func (c *Client) waitForExit(pid int) <-chan struct{} {
c.exitOnce.Do(func() {
func (c *Client) waitForExit(ctx context.Context, pid int) <-chan struct{} {
go c.exitOnce.Do(func() {
defer close(c.exitCh)
ticker := time.NewTicker(10 * time.Millisecond)
defer ticker.Stop()
for {
// use kill(pid, 0) here because the shim could have been reparented
// and we are no longer able to waitpid(pid, ...) on the shim
if err := unix.Kill(pid, 0); err == unix.ESRCH {
close(c.exitCh)
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

View File

@ -26,6 +26,7 @@ import (
"github.com/containerd/containerd/events/exchange"
"github.com/containerd/containerd/log"
"github.com/containerd/containerd/namespaces"
"github.com/containerd/containerd/runtime"
client "github.com/containerd/containerd/runtime/v2/shim"
"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 {
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 {
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 {
return nil, err
}
client := ttrpc.NewClient(conn, ttrpc.WithOnClose(onClose))
onCloseWithShimLog := func() {
onClose()
cancelShimLog()
}
client := ttrpc.NewClient(conn, ttrpc.WithOnClose(onCloseWithShimLog))
return &shim{
bundle: b.bundle,
client: client,

View File

@ -29,6 +29,7 @@ import (
"github.com/containerd/containerd/metadata"
"github.com/containerd/containerd/mount"
"github.com/containerd/containerd/namespaces"
"github.com/containerd/containerd/pkg/timeout"
"github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/runtime"
@ -154,8 +155,13 @@ func (m *TaskManager) Create(ctx context.Context, id string, opts runtime.Create
}
defer func() {
if err != nil {
shim.Shutdown(ctx)
shim.Close()
dctx, cancel := timeout.WithContext(context.Background(), cleanupTimeout)
defer cancel()
_, errShim := shim.Delete(dctx)
if errShim != nil {
shim.Shutdown(dctx)
shim.Close()
}
}
}()
t, err := shim.Create(ctx, opts)

View File

@ -20,6 +20,7 @@ package runc
import (
"context"
"encoding/json"
"io/ioutil"
"os"
"path/filepath"
@ -87,6 +88,10 @@ func NewContainer(ctx context.Context, platform stdio.Platform, r *task.CreateTa
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 {
return nil, err
}
@ -142,6 +147,39 @@ func NewContainer(ctx context.Context, platform stdio.Platform, r *task.CreateTa
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
func ReadRuntime(path string) (string, error) {
data, err := ioutil.ReadFile(filepath.Join(path, "runtime"))

View File

@ -25,7 +25,6 @@ import (
"os"
"os/exec"
"path/filepath"
"strings"
"sync"
"syscall"
"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")
}
go s.forward(ctx, publisher)
if address, err := shim.ReadAddress("address"); err == nil {
s.shimAddress = address
}
return s, nil
}
@ -115,7 +118,8 @@ type service struct {
containers map[string]*runc.Container
cancel func()
shimAddress string
cancel func()
}
func newCommand(ctx context.Context, id, containerdBinary, containerdAddress, containerdTTRPCAddress string) (*exec.Cmd, error) {
@ -158,7 +162,7 @@ func readSpec() (*spec, error) {
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)
if err != nil {
return "", err
@ -174,34 +178,52 @@ func (s *service) StartShim(ctx context.Context, id, containerdBinary, container
break
}
}
address, err := shim.SocketAddress(ctx, grouping)
address, err := shim.SocketAddress(ctx, containerdAddress, grouping)
if err != nil {
return "", err
}
socket, err := shim.NewSocket(address)
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 {
return "", err
return "", errors.Wrap(err, "write existing socket for shim")
}
return address, nil
}
return "", err
if err := shim.RemoveSocket(address); err != nil {
return "", errors.Wrap(err, "remove pre-existing socket")
}
if socket, err = shim.NewSocket(address); err != nil {
return "", errors.Wrap(err, "try create new shim socket 2x")
}
}
defer socket.Close()
defer func() {
if retErr != nil {
socket.Close()
_ = shim.RemoveSocket(address)
}
}()
f, err := socket.File()
if err != nil {
return "", err
}
defer f.Close()
cmd.ExtraFiles = append(cmd.ExtraFiles, f)
if err := cmd.Start(); err != nil {
f.Close()
return "", err
}
defer func() {
if err != nil {
if retErr != nil {
cmd.Process.Kill()
}
}()
@ -251,12 +273,20 @@ func (s *service) Cleanup(ctx context.Context) (*taskAPI.DeleteResponse, error)
if err != nil {
return nil, err
}
runtime, err := runc.ReadRuntime(path)
if err != nil {
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{
Force: true,
}); err != nil {
@ -316,11 +346,12 @@ func (s *service) Start(ctx context.Context, r *taskAPI.StartRequest) (*taskAPI.
s.eventSendMu.Unlock()
return nil, errdefs.ToGRPC(err)
}
if err := s.ep.Add(container.ID, container.Cgroup()); err != nil {
logrus.WithError(err).Error("add cg to OOM monitor")
}
switch r.ExecID {
case "":
if err := s.ep.Add(container.ID, container.Cgroup()); err != nil {
logrus.WithError(err).Error("add cg to OOM monitor")
}
s.send(&eventstypes.TaskStart{
ContainerID: container.ID,
Pid: uint32(p.Pid()),
@ -348,15 +379,11 @@ func (s *service) Delete(ctx context.Context, r *taskAPI.DeleteRequest) (*taskAP
if err != nil {
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 == "" {
s.mu.Lock()
delete(s.containers, r.ID)
hasContainers := len(s.containers) > 0
s.mu.Unlock()
if s.platform != nil && !hasContainers {
s.platform.Close()
}
s.send(&eventstypes.TaskDelete{
ContainerID: container.ID,
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) {
s.mu.Lock()
defer s.mu.Unlock()
// return out if the shim is still servicing containers
if len(s.containers) > 0 {
s.mu.Unlock()
return empty, nil
}
s.cancel()
close(s.events)
if s.platform != nil {
s.platform.Close()
}
if s.shimAddress != "" {
_ = shim.RemoveSocket(s.shimAddress)
}
return empty, nil
}
@ -727,9 +762,7 @@ func (s *service) forward(ctx context.Context, publisher shim.Publisher) {
ns, _ := namespaces.Namespace(ctx)
ctx = namespaces.WithNamespace(context.Background(), ns)
for e := range s.events {
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
err := publisher.Publish(ctx, runc.GetTopic(e), e)
cancel()
if err != nil {
logrus.WithError(err).Error("post event")
}

View File

@ -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
s.rtTasks.Delete(ctx, s.ID())
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()
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 {
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) {
return &process{
p := &process{
id: id,
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) {

View File

@ -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 {
_, 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 {
return nil
}
@ -142,9 +144,9 @@ func (l *RemoteEventsPublisher) forwardRequest(ctx context.Context, req *v1.Forw
return err
}
if _, err := l.client.EventsService().Forward(ctx, req); err != nil {
return err
}
fCtx, cancel = context.WithTimeout(ctx, 5*time.Second)
_, err = l.client.EventsService().Forward(fCtx, req)
cancel()
return nil
return err
}

View File

@ -101,7 +101,7 @@ func parseFlags() {
flag.BoolVar(&debugFlag, "debug", false, "enable debug output in logs")
flag.StringVar(&namespaceFlag, "namespace", "", "namespace that owns the shim")
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(&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 = log.WithLogger(ctx, log.G(ctx).WithField("runtime", id))
ctx, cancel := context.WithCancel(ctx)
service, err := initFunc(ctx, idFlag, publisher, cancel)
if err != nil {
return err
@ -288,11 +287,15 @@ func serve(ctx context.Context, server *ttrpc.Server, path string) error {
return err
}
go func() {
defer l.Close()
if err := server.Serve(ctx, l); err != nil &&
!strings.Contains(err.Error(), "use of closed network connection") {
logrus.WithError(err).Fatal("containerd-shim: ttrpc server failure")
}
l.Close()
if address, err := ReadAddress("address"); err == nil {
_ = RemoveSocket(address)
}
}()
return nil
}

View File

@ -58,15 +58,15 @@ func serveListener(path string) (net.Listener, error) {
l, err = net.FileListener(os.NewFile(3, "socket"))
path = "[inherited from parent]"
} else {
if len(path) > 106 {
return nil, errors.Errorf("%q: unix socket path too long (> 106)", path)
if len(path) > socketPathLimit {
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 {
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
}

View File

@ -169,7 +169,7 @@ func WriteAddress(path, address string) error {
// ErrNoAddress is returned when the address file has no content
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) {
path, err := filepath.Abs(path)
if err != nil {

View File

@ -34,7 +34,10 @@ import (
"github.com/pkg/errors"
)
const shimBinaryFormat = "containerd-shim-%s-%s"
const (
shimBinaryFormat = "containerd-shim-%s-%s"
socketPathLimit = 106
)
func getSysProcAttr() *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
// 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 {
parent := os.Getppid()
score, err := sys.GetOOMScoreAdj(parent)
@ -56,26 +60,30 @@ func AdjustOOMScore(pid int) error {
return errors.Wrap(err, "get parent OOM score")
}
shimScore := score + 1
if shimScore > sys.OOMScoreAdjMax {
shimScore = sys.OOMScoreAdjMax
}
if err := sys.SetOOMScore(pid, shimScore); err != nil {
return errors.Wrap(err, "set shim OOM score")
}
return nil
}
// SocketAddress returns an abstract socket address
func SocketAddress(ctx context.Context, id string) (string, error) {
const socketRoot = "/run/containerd"
// SocketAddress returns a socket address
func SocketAddress(ctx context.Context, socketPath, id string) (string, error) {
ns, err := namespaces.NamespaceRequired(ctx)
if err != nil {
return "", err
}
d := sha256.Sum256([]byte(filepath.Join(ns, id)))
return filepath.Join(string(filepath.Separator), "containerd-shim", fmt.Sprintf("%x.sock", d)), nil
d := sha256.Sum256([]byte(filepath.Join(socketPath, ns, id)))
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) {
address = strings.TrimPrefix(address, "unix://")
return net.DialTimeout("unix", "\x00"+address, timeout)
return net.DialTimeout("unix", socket(address).path(), timeout)
}
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
func NewSocket(address string) (*net.UnixListener, error) {
if len(address) > 106 {
return nil, errors.Errorf("%q: unix socket path too long (> 106)", address)
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", "\x00"+address)
l, err := net.Listen("unix", path)
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
}
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
}

View File

@ -79,3 +79,9 @@ func AnonDialer(address string, timeout time.Duration) (net.Conn, error) {
return c, nil
}
}
// RemoveSocket removes the socket at the specified address if
// it exists on the filesystem
func RemoveSocket(address string) error {
return nil
}

View File

@ -115,7 +115,7 @@ func (s *service) List(req *api.ListContentRequest, session api.Content_ListServ
return nil
}, req.Filters...); err != nil {
return err
return errdefs.ToGRPC(err)
}
if len(buffer) > 0 {

View File

@ -20,7 +20,6 @@ import (
"fmt"
"os"
"path/filepath"
"runtime"
"github.com/containerd/containerd/plugin"
"github.com/pkg/errors"
@ -42,22 +41,20 @@ func init() {
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
path := ic.Config.(*Config).Path
ic.Meta.Exports["path"] = path
bin := filepath.Join(path, "bin")
if err := os.MkdirAll(bin, 0711); err != nil {
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)
}
if runtime.GOOS != "windows" {
lib := filepath.Join(path, "lib")
if err := os.MkdirAll(lib, 0711); err != nil {
return nil, err
}
if err := os.Setenv("LD_LIBRARY_PATH", fmt.Sprintf("%s:%s", os.Getenv("LD_LIBRARY_PATH"), lib)); err != nil {
return nil, errors.Wrapf(err, "set binary lib directory in path %s", lib)
}
lib := filepath.Join(path, "lib")
if err := os.MkdirAll(lib, 0711); err != nil {
return nil, err
}
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 &manager{}, nil
},

View File

@ -118,6 +118,13 @@ func initFunc(ic *plugin.InitContext) (interface{}, error) {
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
}

View File

@ -297,7 +297,7 @@ func Remove(ctx context.Context, key string) (string, snapshots.Kind, error) {
}
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 {

35
vendor/github.com/containerd/containerd/sys/filesys.go generated vendored Normal file
View File

@ -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
}

View File

@ -21,6 +21,7 @@ import (
"syscall"
"unsafe"
"github.com/containerd/containerd/log"
"github.com/pkg/errors"
"golang.org/x/sys/unix"
)
@ -30,9 +31,8 @@ func FMountat(dirfd uintptr, source, target, fstype string, flags uintptr, data
var (
sourceP, targetP, fstypeP, dataP *byte
pid uintptr
ws unix.WaitStatus
err error
errno syscall.Errno
errno, status syscall.Errno
)
sourceP, err = syscall.BytePtrFromString(source)
@ -60,37 +60,62 @@ func FMountat(dirfd uintptr, source, target, fstype string, flags uintptr, data
runtime.LockOSThread()
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,
uintptr(unsafe.Pointer(sourceP)),
uintptr(unsafe.Pointer(targetP)),
uintptr(unsafe.Pointer(fstypeP)),
flags,
uintptr(unsafe.Pointer(dataP)))
uintptr(unsafe.Pointer(dataP)),
pipefds[1],
)
if errno != 0 {
return errors.Wrap(errno, "failed to fork thread")
}
_, err = unix.Wait4(int(pid), &ws, 0, nil)
for err == syscall.EINTR {
_, err = unix.Wait4(int(pid), &ws, 0, nil)
}
defer func() {
_, err := unix.Wait4(int(pid), nil, 0, nil)
for err == syscall.EINTR {
_, err = unix.Wait4(int(pid), nil, 0, nil)
}
if err != nil {
return errors.Wrapf(err, "failed to find pid=%d process", pid)
}
if err != nil {
log.L.WithError(err).Debugf("failed to find pid=%d process", pid)
}
}()
errno = syscall.Errno(ws.ExitStatus())
_, _, 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 mount")
return errors.Wrap(errno, "failed to read pipe")
}
if status != 0 {
return errors.Wrap(status, "failed to mount")
}
return nil
}
// forkAndMountat will fork thread, change working dir and mount.
//
// 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
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)
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)
panic("unreachable")
}

View File

@ -28,8 +28,12 @@ import (
"github.com/opencontainers/runc/libcontainer/system"
)
// OOMScoreMaxKillable is the maximum score keeping the process killable by the oom killer
const OOMScoreMaxKillable = -999
const (
// 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
func SetOOMScore(pid, score int) error {

View File

@ -16,6 +16,11 @@
package sys
const (
// OOMScoreAdjMax is not implemented on Windows
OOMScoreAdjMax = 0
)
// SetOOMScore sets the oom score for the process
//
// Not implemented on Windows

View File

@ -186,8 +186,32 @@ func (u *unpacker) unpack(ctx context.Context, config ocispec.Descriptor, layers
return nil
}
func (u *unpacker) handlerWrapper(uctx context.Context, unpacks *int32) (func(images.Handler) images.Handler, *errgroup.Group) {
eg, uctx := errgroup.WithContext(uctx)
type errGroup struct {
*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 {
var (
lock sync.Mutex
@ -234,7 +258,19 @@ func (u *unpacker) handlerWrapper(uctx context.Context, unpacks *int32) (func(im
update := !schema1
lock.Unlock()
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

View File

@ -1,91 +1,93 @@
github.com/containerd/go-runc e029b79d8cda8374981c64eba71f28ec38e5526f
github.com/containerd/console 0650fd9eeb50bab4fc99dceb9f2e14cf58f36e7f
github.com/containerd/cgroups c4b9ac5c7601384c965b9646fc515884e091ebb9
github.com/containerd/typeurl a93fcdb778cd272c6e9b3028b2f42d813e785d40
github.com/containerd/fifo bda0ff6ed73c67bfb5e62bc9c697f146b7fd7f13
github.com/containerd/btrfs af5082808c833de0e79c1e72eea9fea239364877
github.com/containerd/continuity f2a389ac0a02ce21c09edd7344677a601970f41c
github.com/coreos/go-systemd 48702e0da86bd25e76cfef347e2adeb434a0d0a6
github.com/docker/go-metrics 4ea375f7759c82740c893fc030bc37088d2ec098
github.com/docker/go-events 9461782956ad83b30282bf90e31fa6a70c255ba9
github.com/docker/go-units v0.4.0
github.com/godbus/dbus c7fdd8b5cd55e87b4e1f4e372cdb1db61dd6c66f
github.com/prometheus/client_golang f4fb1b73fb099f396a7f0036bf86aa8def4ed823
github.com/prometheus/client_model 99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c
github.com/prometheus/common 89604d197083d4781071d3c65855d24ecfb0a563
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/beorn7/perks 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9
github.com/BurntSushi/toml v0.3.1
github.com/containerd/btrfs af5082808c833de0e79c1e72eea9fea239364877
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/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/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_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/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944
google.golang.org/grpc v1.23.0
gotest.tools v2.3.0
# cri dependencies
github.com/containerd/cri 5d49e7e51b43e36a6b9c4386257c7d08c602237f # release/1.3
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/docker/distribution 0d3efadf0154c2b8a4e7b6621fff9809655cc580
github.com/docker/docker 86f080cff0914e9694068ed78d503701667c4c00
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.7
github.com/modern-go/reflect2 1.0.1
github.com/modern-go/concurrent 1.0.3
github.com/opencontainers/selinux v1.2.2
github.com/seccomp/libseccomp-golang v0.9.1
github.com/tchap/go-patricia v2.2.6
golang.org/x/crypto 5c40567a22f818bd14a1ea7245dad9f8ef0691aa
golang.org/x/oauth2 0f29369cfe4552d0e4bcddc57cc75f4d7e672a33
golang.org/x/time 85acf8d2951cb2a3bde7632f9ff273ef0379bcbd
gopkg.in/inf.v0 v0.9.0
gopkg.in/yaml.v2 v2.2.2
k8s.io/api kubernetes-1.16.0-rc.2
k8s.io/apimachinery kubernetes-1.16.0-rc.2
k8s.io/apiserver kubernetes-1.16.0-rc.2
k8s.io/cri-api kubernetes-1.16.0-rc.2
k8s.io/client-go kubernetes-1.16.0-rc.2
k8s.io/klog v0.4.0
k8s.io/kubernetes v1.16.0-rc.2
k8s.io/utils c2654d5206da6b7b6ace12841e8f359bb89b443c
sigs.k8s.io/yaml v1.1.0
github.com/containerd/cri v1.3.0-k3s.10 https://github.com/k3s-io/cri.git
github.com/davecgh/go-spew v1.1.1
github.com/docker/distribution 0d3efadf0154c2b8a4e7b6621fff9809655cc580
github.com/docker/docker 86f080cff0914e9694068ed78d503701667c4c00
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 1.0.1
github.com/opencontainers/selinux bb88c45a3863dc4c38320d71b890bb30ef9feba4
github.com/seccomp/libseccomp-golang v0.9.1
github.com/tchap/go-patricia v2.2.6
golang.org/x/crypto 69ecbb4d6d5dab05e49161c6e77ea40a030884e1
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
github.com/containerd/go-cni 49fbd9b210f3c8ee3b7fd3cd797aabaf364627c1
github.com/containernetworking/cni v0.7.1
github.com/containernetworking/plugins v0.7.6
# zfs dependencies
github.com/containerd/zfs 2ceb2dbb8154202ed1b8fd32e4ea25b491d7b251
github.com/mistifyio/go-zfs f784269be439d704d3dfa1906f45dd848fed2beb
github.com/google/uuid v1.1.1
github.com/containerd/zfs 2ceb2dbb8154202ed1b8fd32e4ea25b491d7b251
github.com/mistifyio/go-zfs f784269be439d704d3dfa1906f45dd848fed2beb
# aufs dependencies
github.com/containerd/aufs f894a800659b6e11c1a13084abd1712f346e349c
github.com/containerd/aufs f894a800659b6e11c1a13084abd1712f346e349c

View File

@ -21,7 +21,7 @@ var (
Package = "github.com/containerd/containerd"
// 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
// the program at linking time.

View File

@ -1,23 +1,27 @@
# Copyright 2018 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 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.
GO := go
GOOS := $(shell $(GO) env GOOS)
GOARCH := $(shell $(GO) env GOARCH)
WHALE = "🇩"
ONI = "👹"
EPOCH_TEST_COMMIT := f9e02affccd51702191e5312665a16045ffef8ab
WHALE := "🇩"
ONI := "👹"
ifeq ($(GOOS),windows)
WHALE = "+"
ONI = "-"
endif
EPOCH_TEST_COMMIT := 67de3e4ccf2b2a69b8398798af7cfca01abf7a7e
PROJECT := github.com/containerd/cri
BINDIR := ${DESTDIR}/usr/local/bin
BUILD_DIR := _output
@ -26,35 +30,39 @@ BUILD_DIR := _output
VERSION := $(shell git rev-parse --short HEAD)
TARBALL_PREFIX := cri-containerd
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.
GO_LDFLAGS := -X $(PROJECT)/vendor/github.com/containerd/containerd/version.Version=$(VERSION)-TEST
SOURCES := $(shell find cmd/ pkg/ vendor/ -name '*.go')
PLUGIN_SOURCES := $(shell ls *.go)
INTEGRATION_SOURCES := $(shell find integration/ -name '*.go')
CONTAINERD_BIN := containerd
ifeq ($(GOOS),windows)
CONTAINERD_BIN := $(CONTAINERD_BIN).exe
endif
all: binaries
help: ## this help
@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
@echo $(VERSION)
lint:
@echo "$(WHALE) $@"
golangci-lint run --skip-files .*_test.go
golangci-lint run
gofmt:
@echo "$(WHALE) $@"
@./hack/verify-gofmt.sh
boiler:
@echo "$(WHALE) $@"
@./hack/verify-boilerplate.sh
check-vendor:
@echo "$(WHALE) $@"
@./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
@echo "$(WHALE) $@"
$(BUILD_DIR)/containerd: $(SOURCES) $(PLUGIN_SOURCES)
$(BUILD_DIR)/$(CONTAINERD_BIN): $(SOURCES) $(PLUGIN_SOURCES)
@echo "$(WHALE) $@"
$(GO) build -o $@ \
-tags '$(BUILD_TAGS)' \
@ -84,7 +92,7 @@ test: ## unit test
@echo "$(WHALE) $@"
$(GO) test -timeout=10m -race ./pkg/... \
-tags '$(BUILD_TAGS)' \
-ldflags '$(GO_LDFLAGS)' \
-ldflags '$(GO_LDFLAGS)' \
-gcflags '$(GO_GCFLAGS)'
$(BUILD_DIR)/integration.test: $(INTEGRATION_SOURCES)
@ -107,29 +115,34 @@ clean: ## cleanup binaries
@echo "$(WHALE) $@"
@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) $@"
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) $@"
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) $@"
install-containerd: containerd ## installs customized containerd to system location
@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
@echo "$(WHALE) $@"
uninstall: ## remove containerd from system location
@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=$(BUILD_DIR) TARBALL=$(TARBALL) VERSION=$(VERSION) ./hack/release.sh
endif
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/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) $@"
@./hack/install/install-deps.sh
.install.deps.windows: ## install dependencies of cri on windows
@echo "$(WHALE) $@"
@./hack/install/windows/install-deps.sh
.PHONY: .gitvalidation
# When this is running in travis, it will only check the travis commit range.
# When running outside travis, it will check from $(EPOCH_TEST_COMMIT)..HEAD.
# make .gitvalidation is only used localy for manual testing
# requires a clone of github.com/containerd/project
# containerd/project DCO validation runs automatically with github actions in ci.yml for each pull
.gitvalidation:
@echo "$(WHALE) $@"
ifeq ($(TRAVIS),true)
git-validation -q -run DCO,short-subject
else
git-validation -v -run DCO,short-subject -range $(EPOCH_TEST_COMMIT)..HEAD
endif
DCO_VERBOSITY=-v DCO_RANGE=$(EPOCH_TEST_COMMIT)..HEAD ../project/script/validate/dco
.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:
@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; \
git checkout v1.18.0; \
go install
GO111MODULE=off go install
.install.vndr:
@echo "$(WHALE) $@"
@ -186,7 +206,6 @@ install.tools: .install.gitvalidation .install.golangci-lint .install.vndr ## in
install-containerd \
release \
push \
boiler \
clean \
default \
gofmt \

View File

@ -63,6 +63,10 @@ func initCRIService(ic *plugin.InitContext) (interface{}, error) {
ic.Meta.Exports = map[string]string{"CRIVersion": constants.CRIVersion}
ctx := ic.Context
pluginConfig := ic.Config.(*criconfig.PluginConfig)
if err := criconfig.ValidatePluginConfig(ctx, pluginConfig); err != nil {
return nil, errors.Wrap(err, "invalid plugin config")
}
c := criconfig.Config{
PluginConfig: *pluginConfig,
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)
if err := criconfig.ValidatePluginConfig(ctx, pluginConfig); err != nil {
return nil, errors.Wrap(err, "invalid plugin config")
}
if err := setGLogLevel(); err != nil {
return nil, errors.Wrap(err, "failed to set glog level")
}

View File

@ -122,9 +122,10 @@ type AuthConfig struct {
// TLSConfig contains the CA/Cert/Key used for a registry
type TLSConfig struct {
CAFile string `toml:"ca_file" json:"caFile"`
CertFile string `toml:"cert_file" json:"certFile"`
KeyFile string `toml:"key_file" json:"keyFile"`
InsecureSkipVerify bool `toml:"insecure_skip_verify" json:"insecure_skip_verify"`
CAFile string `toml:"ca_file" json:"caFile"`
CertFile string `toml:"cert_file" json:"certFile"`
KeyFile string `toml:"key_file" json:"keyFile"`
}
// Registry is registry settings configured

View File

@ -265,7 +265,7 @@ func WithMounts(osi osinterface.OS, config *runtime.ContainerConfig, extra []*ru
}
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)
}
}

View File

@ -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
}

View 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
}

View File

@ -39,6 +39,8 @@ import (
"github.com/davecgh/go-spew/spew"
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
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"
"golang.org/x/net/context"
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)
}
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))
// 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,
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{
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
// can override them.
env := imageConfig.Env
env := append([]string{}, imageConfig.Env...)
for _, e := range config.GetEnvs() {
env = append(env, e.GetKey()+"="+e.GetValue())
}
specOpts = append(specOpts, oci.WithEnv(env))
securityContext := config.GetLinux().GetSecurityContext()
selinuxOpt := securityContext.GetSelinuxOptions()
processLabel, mountLabel, err := initSelinuxOpts(selinuxOpt)
labelOptions, err := toLabel(securityContext.GetSelinuxOptions())
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 {
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))
if !c.config.DisableProcMount {
@ -461,10 +493,10 @@ func (c *criService) generateVolumeMounts(containerRootDir string, criMounts []*
src := filepath.Join(containerRootDir, "volumes", volumeID)
// addOCIBindMounts will create these volumes.
mounts = append(mounts, &runtime.Mount{
ContainerPath: dst,
HostPath: src,
ContainerPath: dst,
HostPath: src,
SelinuxRelabel: true,
// Use default mount propagation.
// TODO(random-liu): What about selinux relabel?
})
}
return mounts
@ -515,9 +547,10 @@ func (c *criService) generateContainerMounts(sandboxID string, config *runtime.C
sandboxDevShm = devShm
}
mounts = append(mounts, &runtime.Mount{
ContainerPath: devShm,
HostPath: sandboxDevShm,
Readonly: false,
ContainerPath: devShm,
HostPath: sandboxDevShm,
Readonly: false,
SelinuxRelabel: sandboxDevShm != devShm,
})
}
return mounts

View File

@ -22,6 +22,7 @@ import (
"github.com/containerd/containerd/log"
"github.com/docker/docker/pkg/system"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"golang.org/x/net/context"
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
@ -30,7 +31,6 @@ import (
)
// 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) {
container, err := c.containerStore.Get(r.GetContainerId())
if err != nil {
@ -43,6 +43,17 @@ func (c *criService) RemoveContainer(ctx context.Context, r *runtime.RemoveConta
}
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
// while it's being removed.
if err := setContainerRemoving(container); err != nil {

View File

@ -333,6 +333,12 @@ func handleContainerExit(ctx context.Context, e *eventtypes.TaskExit, cntr conta
status.Pid = 0
status.FinishedAt = e.ExitedAt.UnixNano()
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
})
if err != nil {

View File

@ -298,47 +298,63 @@ func (c *criService) ensureImageExists(ctx context.Context, ref string, config *
return &newImage, nil
}
func initSelinuxOpts(selinuxOpt *runtime.SELinuxOption) (string, string, error) {
if selinuxOpt == nil {
return "", "", nil
func toLabel(selinuxOptions *runtime.SELinuxOption) ([]string, error) {
var labels []string
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.
if selinuxOpt.GetUser() == "" ||
selinuxOpt.GetRole() == "" ||
selinuxOpt.GetType() == "" {
return "", "", nil
}
return labels, nil
}
// make sure the format of "level" is correct.
ok, err := checkSelinuxLevel(selinuxOpt.GetLevel())
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)
func initLabelsFromOpt(selinuxOpts *runtime.SELinuxOption) (string, string, error) {
labels, err := toLabel(selinuxOpts)
if err != nil {
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)
}
func checkSelinuxLevel(level string) (bool, error) {
func checkSelinuxLevel(level string) error {
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)
if err != nil || !matched {
return false, errors.Wrapf(err, "the format of 'level' %q is not correct", 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 {
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.
@ -465,6 +481,7 @@ func unknownContainerStatus() containerstore.Status {
FinishedAt: 0,
ExitCode: unknownExitCode,
Reason: unknownExitReason,
Unknown: true,
}
}

View File

@ -253,39 +253,41 @@ func (c *criService) updateImage(ctx context.Context, r string) error {
// getTLSConfig returns a TLSConfig configured with a CA/Cert/Key specified by registryTLSConfig
func (c *criService) getTLSConfig(registryTLSConfig criconfig.TLSConfig) (*tls.Config, error) {
var (
cert tls.Certificate
err error
tlsConfig = &tls.Config{}
cert tls.Certificate
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 == "" {
return nil, errors.Errorf("cert file %q was specified, but no corresponding key file was specified", registryTLSConfig.CertFile)
}
if registryTLSConfig.CertFile == "" && 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
}
caCertPool, err := x509.SystemCertPool()
if err != nil {
return nil, errors.Wrap(err, "failed to get system cert pool")
if registryTLSConfig.CAFile != "" {
caCertPool, err := x509.SystemCertPool()
if err != nil {
return nil, errors.Wrap(err, "failed to get system cert pool")
}
caCert, err := ioutil.ReadFile(registryTLSConfig.CAFile)
if err != nil {
return nil, errors.Wrap(err, "failed to load CA file")
}
caCertPool.AppendCertsFromPEM(caCert)
tlsConfig.RootCAs = caCertPool
}
caCert, err := ioutil.ReadFile(registryTLSConfig.CAFile)
if err != nil {
return nil, errors.Wrap(err, "failed to load CA file")
}
caCertPool.AppendCertsFromPEM(caCert)
tlsConfig := &tls.Config{
RootCAs: caCertPool,
}
if len(cert.Certificate) != 0 {
tlsConfig.Certificates = []tls.Certificate{cert}
}
tlsConfig.BuildNameToCertificate()
tlsConfig.InsecureSkipVerify = registryTLSConfig.InsecureSkipVerify
return tlsConfig, nil
}

View File

@ -307,7 +307,9 @@ func (c *criService) loadContainer(ctx context.Context, cntr containerd.Containe
}()
if err != nil {
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{
containerstore.WithStatus(status, containerDir),

View File

@ -22,6 +22,7 @@ import (
"github.com/containerd/containerd/log"
"github.com/docker/docker/pkg/system"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"golang.org/x/net/context"
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.
state := sandbox.Status.Get().State
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.

View File

@ -34,6 +34,7 @@ import (
"github.com/davecgh/go-spew/spew"
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
runtimespec "github.com/opencontainers/runtime-spec/specs-go"
selinux "github.com/opencontainers/selinux/go-selinux"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"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")
}
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
userstr, err := generateUserString(
@ -271,7 +284,7 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox
var taskOpts []containerd.NewTaskOpts
// 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)
}
// 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,
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.
// TODO(random-liu): [P1] Compare the default settings with docker and containerd default.
specOpts := []oci.SpecOpts{
@ -403,11 +416,15 @@ func (c *criService) generateSandboxContainerSpec(id string, config *runtime.Pod
},
}))
selinuxOpt := securityContext.GetSelinuxOptions()
processLabel, mountLabel, err := initSelinuxOpts(selinuxOpt)
processLabel, mountLabel, err := initLabelsFromOpt(securityContext.GetSelinuxOptions())
if err != nil {
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()
specOpts = append(specOpts,

View File

@ -1,17 +1,17 @@
/*
Copyright 2017 The Kubernetes Authors.
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
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
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.
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 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",
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.
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
// if a container is removed after list.
if err = c.stopContainer(ctx, container, 0); err != nil {
return nil, errors.Wrapf(err, "failed to stop container %q", container.ID)
if err := c.stopContainer(ctx, container, 0); err != nil {
return errors.Wrapf(err, "failed to stop container %q", container.ID)
}
}
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.
state := sandbox.Status.Get().State
if state == sandboxstore.StateReady || state == sandboxstore.StateUnknown {
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:
// https://github.com/containernetworking/cni/blob/v0.7.0-alpha1/SPEC.md
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 {
sandbox.NetNSPath = ""
}
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 {
return nil, errors.Wrapf(err, "failed to remove network namespace for sandbox %q", id)
if err := sandbox.NetNS.Remove(); err != nil {
return errors.Wrapf(err, "failed to remove network namespace for sandbox %q", id)
}
}
log.G(ctx).Infof("TearDown network for sandbox %q successfully", id)
return &runtime.StopPodSandboxResponse{}, nil
return nil
}
// stopSandboxContainer kills the sandbox container.

View File

@ -25,9 +25,9 @@ import (
"github.com/containerd/containerd"
"github.com/containerd/containerd/plugin"
"github.com/containerd/cri/pkg/store/label"
cni "github.com/containerd/go-cni"
runcapparmor "github.com/opencontainers/runc/libcontainer/apparmor"
runcseccomp "github.com/opencontainers/runc/libcontainer/seccomp"
runcsystem "github.com/opencontainers/runc/libcontainer/system"
"github.com/opencontainers/selinux/go-selinux"
"github.com/pkg/errors"
@ -41,6 +41,7 @@ import (
ctrdutil "github.com/containerd/cri/pkg/containerd/util"
osinterface "github.com/containerd/cri/pkg/os"
"github.com/containerd/cri/pkg/registrar"
"github.com/containerd/cri/pkg/seccomp"
containerstore "github.com/containerd/cri/pkg/store/container"
imagestore "github.com/containerd/cri/pkg/store/image"
sandboxstore "github.com/containerd/cri/pkg/store/sandbox"
@ -104,14 +105,15 @@ type criService struct {
// NewCRIService returns a new instance of CRIService
func NewCRIService(config criconfig.Config, client *containerd.Client) (CRIService, error) {
var err error
labels := label.NewStore()
c := &criService{
config: config,
client: client,
apparmorEnabled: runcapparmor.IsEnabled() && !config.DisableApparmor,
seccompEnabled: runcseccomp.IsEnabled(),
seccompEnabled: seccomp.IsEnabled(),
os: osinterface.RealOS{},
sandboxStore: sandboxstore.NewStore(),
containerStore: containerstore.NewStore(),
sandboxStore: sandboxstore.NewStore(labels),
containerStore: containerstore.NewStore(labels),
imageStore: imagestore.NewStore(client),
snapshotStore: snapshotstore.NewStore(),
sandboxNameIndex: registrar.NewRegistrar(),

View File

@ -68,7 +68,7 @@ func getStreamListenerMode(c *criService) (streamListenerMode, error) {
func newStreamServer(c *criService, addr, port, streamIdleTimeout string) (streaming.Server, error) {
if addr == "" {
a, err := k8snet.ChooseBindAddress(nil)
a, err := k8snet.ChooseHostInterface()
if err != nil {
return nil, errors.Wrap(err, "failed to get stream server address")
}

View File

@ -20,6 +20,7 @@ import (
"sync"
"github.com/containerd/containerd"
"github.com/containerd/cri/pkg/store/label"
"github.com/docker/docker/pkg/truncindex"
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
@ -101,13 +102,15 @@ type Store struct {
lock sync.RWMutex
containers map[string]Container
idIndex *truncindex.TruncIndex
labels *label.Store
}
// NewStore creates a container store.
func NewStore() *Store {
func NewStore(labels *label.Store) *Store {
return &Store{
containers: make(map[string]Container),
idIndex: truncindex.NewTruncIndex([]string{}),
labels: labels,
}
}
@ -119,6 +122,9 @@ func (s *Store) Add(c Container) error {
if _, ok := s.containers[c.ID]; ok {
return store.ErrAlreadyExist
}
if err := s.labels.Reserve(c.ProcessLabel); err != nil {
return err
}
if err := s.idIndex.Add(c.ID); err != nil {
return err
}
@ -165,6 +171,7 @@ func (s *Store) Delete(id string) {
// So we need to return if there are error.
return
}
s.labels.Release(s.containers[id].ProcessLabel)
s.idIndex.Delete(id) // nolint: errcheck
delete(s.containers, id)
}

View File

@ -61,6 +61,8 @@ type Metadata struct {
// StopSignal is the system call signal that will be sent to the container to exit.
// TODO(random-liu): Add integration test for stop signal.
StopSignal string
// ProcessLabel is the SELinux process label for the container
ProcessLabel string
}
// MarshalJSON encodes Metadata into bytes in json format.

View File

@ -94,10 +94,16 @@ type Status struct {
// Removing indicates that the container is in removing state.
// This field doesn't need to be checkpointed.
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.
func (s Status) State() runtime.ContainerState {
if s.Unknown {
return runtime.ContainerState_CONTAINER_UNKNOWN
}
if s.FinishedAt != 0 {
return runtime.ContainerState_CONTAINER_EXITED
}

View File

@ -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
}
}

View File

@ -61,6 +61,8 @@ type Metadata struct {
RuntimeHandler string
// CNIresult resulting configuration for attached network namespace interfaces
CNIResult *cni.CNIResult
// ProcessLabel is the SELinux process label for the container
ProcessLabel string
}
// MarshalJSON encodes Metadata into bytes in json format.

View File

@ -20,6 +20,7 @@ import (
"sync"
"github.com/containerd/containerd"
"github.com/containerd/cri/pkg/store/label"
"github.com/docker/docker/pkg/truncindex"
"github.com/containerd/cri/pkg/netns"
@ -62,13 +63,15 @@ type Store struct {
lock sync.RWMutex
sandboxes map[string]Sandbox
idIndex *truncindex.TruncIndex
labels *label.Store
}
// NewStore creates a sandbox store.
func NewStore() *Store {
func NewStore(labels *label.Store) *Store {
return &Store{
sandboxes: make(map[string]Sandbox),
idIndex: truncindex.NewTruncIndex([]string{}),
labels: labels,
}
}
@ -79,6 +82,9 @@ func (s *Store) Add(sb Sandbox) error {
if _, ok := s.sandboxes[sb.ID]; ok {
return store.ErrAlreadyExist
}
if err := s.labels.Reserve(sb.ProcessLabel); err != nil {
return err
}
if err := s.idIndex.Add(sb.ID); err != nil {
return err
}
@ -125,6 +131,7 @@ func (s *Store) Delete(id string) {
// So we need to return if there are error.
return
}
s.labels.Release(s.sandboxes[id].ProcessLabel)
s.idIndex.Delete(id) // nolint: errcheck
delete(s.sandboxes, id)
}

View File

@ -1,81 +1,87 @@
# 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
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/Microsoft/hcsshim 9e921883ac929bbe515b39793ece99ce3a9d7706
github.com/Microsoft/go-winio v0.4.14
github.com/BurntSushi/toml v0.3.1
github.com/imdario/mergo v0.3.7
github.com/beorn7/perks 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9
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/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
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
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

354
vendor/github.com/hashicorp/errwrap/LICENSE generated vendored Normal file
View File

@ -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 Contributors 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 partys
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
partys 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 partys 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.

89
vendor/github.com/hashicorp/errwrap/README.md generated vendored Normal file
View File

@ -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!
}
```

169
vendor/github.com/hashicorp/errwrap/errwrap.go generated vendored Normal file
View File

@ -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}
}

12
vendor/github.com/hashicorp/go-multierror/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,12 @@
sudo: false
language: go
go:
- 1.6
branches:
only:
- master
script: make test testrace

353
vendor/github.com/hashicorp/go-multierror/LICENSE generated vendored Normal file
View File

@ -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 Contributors 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 partys
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
partys 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 partys 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.

31
vendor/github.com/hashicorp/go-multierror/Makefile generated vendored Normal file
View File

@ -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