Add golint to test (#255)
* Add a new lint rule to the Makefile Signed-off-by: Kenfe-Mickael Laventure <mickael.laventure@gmail.com> * Fix linter errors Signed-off-by: Kenfe-Mickael Laventure <mickael.laventure@gmail.com> * Allow replacing the default apt mirror Signed-off-by: Kenfe-Mickael Laventure <mickael.laventure@gmail.com>
This commit is contained in:
parent
4176ba7b52
commit
5624732128
38 changed files with 297 additions and 151 deletions
18
Dockerfile
18
Dockerfile
|
@ -1,5 +1,9 @@
|
||||||
FROM debian:jessie
|
FROM debian:jessie
|
||||||
|
|
||||||
|
# allow replacing httpredir mirror
|
||||||
|
ARG APT_MIRROR=httpredir.debian.org
|
||||||
|
RUN sed -i s/httpredir.debian.org/$APT_MIRROR/g /etc/apt/sources.list
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y \
|
RUN apt-get update && apt-get install -y \
|
||||||
build-essential \
|
build-essential \
|
||||||
ca-certificates \
|
ca-certificates \
|
||||||
|
@ -18,6 +22,20 @@ RUN curl -sSL "https://storage.googleapis.com/golang/go${GO_VERSION}.linux-amd6
|
||||||
ENV PATH /go/bin:/usr/local/go/bin:$PATH
|
ENV PATH /go/bin:/usr/local/go/bin:$PATH
|
||||||
ENV GOPATH /go:/go/src/github.com/docker/containerd/vendor
|
ENV GOPATH /go:/go/src/github.com/docker/containerd/vendor
|
||||||
|
|
||||||
|
ENV GO_TOOLS_COMMIT 823804e1ae08dbb14eb807afc7db9993bc9e3cc3
|
||||||
|
# Grab Go's cover tool for dead-simple code coverage testing
|
||||||
|
# Grab Go's vet tool for examining go code to find suspicious constructs
|
||||||
|
# and help prevent errors that the compiler might not catch
|
||||||
|
RUN git clone https://github.com/golang/tools.git /go/src/golang.org/x/tools \
|
||||||
|
&& (cd /go/src/golang.org/x/tools && git checkout -q $GO_TOOLS_COMMIT) \
|
||||||
|
&& go install -v golang.org/x/tools/cmd/cover \
|
||||||
|
&& go install -v golang.org/x/tools/cmd/vet
|
||||||
|
# Grab Go's lint tool
|
||||||
|
ENV GO_LINT_COMMIT 32a87160691b3c96046c0c678fe57c5bef761456
|
||||||
|
RUN git clone https://github.com/golang/lint.git /go/src/github.com/golang/lint \
|
||||||
|
&& (cd /go/src/github.com/golang/lint && git checkout -q $GO_LINT_COMMIT) \
|
||||||
|
&& go install -v github.com/golang/lint/golint
|
||||||
|
|
||||||
WORKDIR /go/src/github.com/docker/containerd
|
WORKDIR /go/src/github.com/docker/containerd
|
||||||
|
|
||||||
# install seccomp: the version shipped in trusty is too old
|
# install seccomp: the version shipped in trusty is too old
|
||||||
|
|
4
Makefile
4
Makefile
|
@ -80,7 +80,7 @@ fmt:
|
||||||
@gofmt -s -l . | grep -v vendor | grep -v .pb. | tee /dev/stderr
|
@gofmt -s -l . | grep -v vendor | grep -v .pb. | tee /dev/stderr
|
||||||
|
|
||||||
lint:
|
lint:
|
||||||
@golint ./... | grep -v vendor | grep -v .pb. | tee /dev/stderr
|
@hack/validate-lint
|
||||||
|
|
||||||
shell: dbuild
|
shell: dbuild
|
||||||
$(DOCKER_RUN) bash
|
$(DOCKER_RUN) bash
|
||||||
|
@ -95,7 +95,7 @@ endif
|
||||||
bench: shim validate install bundles-rootfs
|
bench: shim validate install bundles-rootfs
|
||||||
go test -bench=. -v $(shell go list ./... | grep -v /vendor | grep -v /integration-test)
|
go test -bench=. -v $(shell go list ./... | grep -v /vendor | grep -v /integration-test)
|
||||||
|
|
||||||
validate: fmt
|
validate: fmt lint
|
||||||
|
|
||||||
uninstall:
|
uninstall:
|
||||||
$(foreach file,containerd containerd-shim ctr,rm /usr/local/bin/$(file);)
|
$(foreach file,containerd containerd-shim ctr,rm /usr/local/bin/$(file);)
|
||||||
|
|
|
@ -82,7 +82,7 @@ func (s *apiServer) CreateCheckpoint(ctx context.Context, r *types.CreateCheckpo
|
||||||
e.Checkpoint = &runtime.Checkpoint{
|
e.Checkpoint = &runtime.Checkpoint{
|
||||||
Name: r.Checkpoint.Name,
|
Name: r.Checkpoint.Name,
|
||||||
Exit: r.Checkpoint.Exit,
|
Exit: r.Checkpoint.Exit,
|
||||||
Tcp: r.Checkpoint.Tcp,
|
TCP: r.Checkpoint.Tcp,
|
||||||
UnixSockets: r.Checkpoint.UnixSockets,
|
UnixSockets: r.Checkpoint.UnixSockets,
|
||||||
Shell: r.Checkpoint.Shell,
|
Shell: r.Checkpoint.Shell,
|
||||||
}
|
}
|
||||||
|
@ -135,7 +135,7 @@ func (s *apiServer) ListCheckpoint(ctx context.Context, r *types.ListCheckpointR
|
||||||
for _, c := range checkpoints {
|
for _, c := range checkpoints {
|
||||||
out = append(out, &types.Checkpoint{
|
out = append(out, &types.Checkpoint{
|
||||||
Name: c.Name,
|
Name: c.Name,
|
||||||
Tcp: c.Tcp,
|
Tcp: c.TCP,
|
||||||
Shell: c.Shell,
|
Shell: c.Shell,
|
||||||
UnixSockets: c.UnixSockets,
|
UnixSockets: c.UnixSockets,
|
||||||
// TODO: figure out timestamp
|
// TODO: figure out timestamp
|
||||||
|
@ -333,15 +333,15 @@ func convertToPb(st *runtime.Stat) *types.StatsResponse {
|
||||||
systemUsage, _ := getSystemCPUUsage()
|
systemUsage, _ := getSystemCPUUsage()
|
||||||
pbSt.CgroupStats.CpuStats = &types.CpuStats{
|
pbSt.CgroupStats.CpuStats = &types.CpuStats{
|
||||||
CpuUsage: &types.CpuUsage{
|
CpuUsage: &types.CpuUsage{
|
||||||
TotalUsage: st.Cpu.Usage.Total,
|
TotalUsage: st.CPU.Usage.Total,
|
||||||
PercpuUsage: st.Cpu.Usage.Percpu,
|
PercpuUsage: st.CPU.Usage.Percpu,
|
||||||
UsageInKernelmode: st.Cpu.Usage.Kernel,
|
UsageInKernelmode: st.CPU.Usage.Kernel,
|
||||||
UsageInUsermode: st.Cpu.Usage.User,
|
UsageInUsermode: st.CPU.Usage.User,
|
||||||
},
|
},
|
||||||
ThrottlingData: &types.ThrottlingData{
|
ThrottlingData: &types.ThrottlingData{
|
||||||
Periods: st.Cpu.Throttling.Periods,
|
Periods: st.CPU.Throttling.Periods,
|
||||||
ThrottledPeriods: st.Cpu.Throttling.ThrottledPeriods,
|
ThrottledPeriods: st.CPU.Throttling.ThrottledPeriods,
|
||||||
ThrottledTime: st.Cpu.Throttling.ThrottledTime,
|
ThrottledTime: st.CPU.Throttling.ThrottledTime,
|
||||||
},
|
},
|
||||||
SystemUsage: systemUsage,
|
SystemUsage: systemUsage,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package pprof
|
package pprof
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
// expvar init routine adds the "/debug/vars" handler
|
||||||
_ "expvar"
|
_ "expvar"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/pprof"
|
"net/http/pprof"
|
||||||
|
@ -8,6 +9,7 @@ import (
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Enable registers the "/debug/pprof" handler
|
||||||
func Enable(address string) {
|
func Enable(address string) {
|
||||||
http.Handle("/", http.RedirectHandler("/debug/pprof", http.StatusMovedPermanently))
|
http.Handle("/", http.RedirectHandler("/debug/pprof", http.StatusMovedPermanently))
|
||||||
|
|
||||||
|
|
|
@ -6,14 +6,17 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// EpollCreate1 directly calls syscall.EpollCreate1
|
||||||
func EpollCreate1(flag int) (int, error) {
|
func EpollCreate1(flag int) (int, error) {
|
||||||
return syscall.EpollCreate1(flag)
|
return syscall.EpollCreate1(flag)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EpollCtl directly calls syscall.EpollCtl
|
||||||
func EpollCtl(epfd int, op int, fd int, event *syscall.EpollEvent) error {
|
func EpollCtl(epfd int, op int, fd int, event *syscall.EpollEvent) error {
|
||||||
return syscall.EpollCtl(epfd, op, fd, event)
|
return syscall.EpollCtl(epfd, op, fd, event)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EpollWait directly calls syscall.EpollWait
|
||||||
func EpollWait(epfd int, events []syscall.EpollEvent, msec int) (int, error) {
|
func EpollWait(epfd int, events []syscall.EpollEvent, msec int) (int, error) {
|
||||||
return syscall.EpollWait(epfd, events, msec)
|
return syscall.EpollWait(epfd, events, msec)
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@ import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// EpollCreate1 calls a C implementation
|
||||||
func EpollCreate1(flag int) (int, error) {
|
func EpollCreate1(flag int) (int, error) {
|
||||||
fd := int(C.EpollCreate1(C.int(flag)))
|
fd := int(C.EpollCreate1(C.int(flag)))
|
||||||
if fd < 0 {
|
if fd < 0 {
|
||||||
|
@ -48,6 +49,7 @@ func EpollCreate1(flag int) (int, error) {
|
||||||
return fd, nil
|
return fd, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EpollCtl calls a C implementation
|
||||||
func EpollCtl(epfd int, op int, fd int, event *syscall.EpollEvent) error {
|
func EpollCtl(epfd int, op int, fd int, event *syscall.EpollEvent) error {
|
||||||
errno := C.EpollCtl(C.int(epfd), C.int(syscall.EPOLL_CTL_ADD), C.int(fd), C.int(event.Events), C.int(event.Fd))
|
errno := C.EpollCtl(C.int(epfd), C.int(syscall.EPOLL_CTL_ADD), C.int(fd), C.int(event.Events), C.int(event.Fd))
|
||||||
if errno < 0 {
|
if errno < 0 {
|
||||||
|
@ -56,6 +58,7 @@ func EpollCtl(epfd int, op int, fd int, event *syscall.EpollEvent) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EpollWait calls a C implementation
|
||||||
func EpollWait(epfd int, events []syscall.EpollEvent, msec int) (int, error) {
|
func EpollWait(epfd int, events []syscall.EpollEvent, msec int) (int, error) {
|
||||||
var c_events [128]C.struct_event_t
|
var c_events [128]C.struct_event_t
|
||||||
n := int(C.run_epoll_wait(C.int(epfd), (*C.struct_event_t)(unsafe.Pointer(&c_events))))
|
n := int(C.run_epoll_wait(C.int(epfd), (*C.struct_event_t)(unsafe.Pointer(&c_events))))
|
||||||
|
|
|
@ -24,8 +24,8 @@ type checkpoint struct {
|
||||||
Created time.Time `json:"created"`
|
Created time.Time `json:"created"`
|
||||||
// Name is the name of the checkpoint
|
// Name is the name of the checkpoint
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
// Tcp checkpoints open tcp connections
|
// TCP checkpoints open tcp connections
|
||||||
Tcp bool `json:"tcp"`
|
TCP bool `json:"tcp"`
|
||||||
// UnixSockets persists unix sockets in the checkpoint
|
// UnixSockets persists unix sockets in the checkpoint
|
||||||
UnixSockets bool `json:"unixSockets"`
|
UnixSockets bool `json:"unixSockets"`
|
||||||
// Shell persists tty sessions in the checkpoint
|
// Shell persists tty sessions in the checkpoint
|
||||||
|
@ -140,7 +140,7 @@ func (p *process) start() error {
|
||||||
if p.checkpoint.Shell {
|
if p.checkpoint.Shell {
|
||||||
add("--shell-job")
|
add("--shell-job")
|
||||||
}
|
}
|
||||||
if p.checkpoint.Tcp {
|
if p.checkpoint.TCP {
|
||||||
add("--tcp-established")
|
add("--tcp-established")
|
||||||
}
|
}
|
||||||
if p.checkpoint.UnixSockets {
|
if p.checkpoint.UnixSockets {
|
||||||
|
@ -292,6 +292,7 @@ func (p *process) openIO() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IO holds all 3 standard io Reader/Writer (stdin,stdout,stderr)
|
||||||
type IO struct {
|
type IO struct {
|
||||||
Stdin io.WriteCloser
|
Stdin io.WriteCloser
|
||||||
Stdout io.ReadCloser
|
Stdout io.ReadCloser
|
||||||
|
|
|
@ -15,7 +15,7 @@ import (
|
||||||
|
|
||||||
const usage = `High performance container daemon cli`
|
const usage = `High performance container daemon cli`
|
||||||
|
|
||||||
type Exit struct {
|
type exit struct {
|
||||||
Code int
|
Code int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ func main() {
|
||||||
// We want our defer functions to be run when calling fatal()
|
// We want our defer functions to be run when calling fatal()
|
||||||
defer func() {
|
defer func() {
|
||||||
if e := recover(); e != nil {
|
if e := recover(); e != nil {
|
||||||
if ex, ok := e.(Exit); ok == true {
|
if ex, ok := e.(exit); ok == true {
|
||||||
os.Exit(ex.Code)
|
os.Exit(ex.Code)
|
||||||
}
|
}
|
||||||
panic(e)
|
panic(e)
|
||||||
|
@ -86,5 +86,5 @@ var versionCommand = cli.Command{
|
||||||
|
|
||||||
func fatal(err string, code int) {
|
func fatal(err string, code int) {
|
||||||
fmt.Fprintf(os.Stderr, "[ctr] %s\n", err)
|
fmt.Fprintf(os.Stderr, "[ctr] %s\n", err)
|
||||||
panic(Exit{code})
|
panic(exit{code})
|
||||||
}
|
}
|
||||||
|
|
9
hack/validate-lint
Executable file
9
hack/validate-lint
Executable file
|
@ -0,0 +1,9 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
lint_error=$(golint ./... | grep -v vendor | grep -v .pb. | tee /dev/stderr)
|
||||||
|
|
||||||
|
if [ "$lint_error" != "" ]; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 0
|
|
@ -44,14 +44,14 @@ func untarRootfs(source string, destination string) error {
|
||||||
func CreateBundleWithFilter(source, name string, args []string, filter func(spec *ocs.Spec)) error {
|
func CreateBundleWithFilter(source, name string, args []string, filter func(spec *ocs.Spec)) error {
|
||||||
// Generate the spec
|
// Generate the spec
|
||||||
var spec ocs.Spec
|
var spec ocs.Spec
|
||||||
if f, err := os.Open(utils.RefOciSpecsPath); err != nil {
|
f, err := os.Open(utils.RefOciSpecsPath)
|
||||||
|
if err != nil {
|
||||||
return fmt.Errorf("Failed to open default spec: %v", err)
|
return fmt.Errorf("Failed to open default spec: %v", err)
|
||||||
} else {
|
|
||||||
if err := json.NewDecoder(f).Decode(&spec); err != nil {
|
|
||||||
return fmt.Errorf("Failed to load default spec: %v", err)
|
|
||||||
}
|
|
||||||
f.Close()
|
|
||||||
}
|
}
|
||||||
|
if err := json.NewDecoder(f).Decode(&spec); err != nil {
|
||||||
|
return fmt.Errorf("Failed to load default spec: %v", err)
|
||||||
|
}
|
||||||
|
f.Close()
|
||||||
|
|
||||||
spec.Process.Args = args
|
spec.Process.Args = args
|
||||||
spec.Process.Terminal = false
|
spec.Process.Terminal = false
|
||||||
|
|
|
@ -21,10 +21,10 @@ func (cs *ContainerdSuite) ListRunningContainers() ([]*types.Container, error) {
|
||||||
return resp.Containers, nil
|
return resp.Containers, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *ContainerdSuite) SignalContainerProcess(id string, procId string, sig uint32) error {
|
func (cs *ContainerdSuite) SignalContainerProcess(id string, procID string, sig uint32) error {
|
||||||
_, err := cs.grpcClient.Signal(context.Background(), &types.SignalRequest{
|
_, err := cs.grpcClient.Signal(context.Background(), &types.SignalRequest{
|
||||||
Id: id,
|
Id: id,
|
||||||
Pid: procId,
|
Pid: procID,
|
||||||
Signal: sig,
|
Signal: sig,
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
|
@ -74,8 +74,8 @@ type stdio struct {
|
||||||
stderrBuffer bytes.Buffer
|
stderrBuffer bytes.Buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
type containerProcess struct {
|
type ContainerProcess struct {
|
||||||
containerId string
|
containerID string
|
||||||
pid string
|
pid string
|
||||||
bundle *Bundle
|
bundle *Bundle
|
||||||
io stdio
|
io stdio
|
||||||
|
@ -84,7 +84,7 @@ type containerProcess struct {
|
||||||
hasExited bool
|
hasExited bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *containerProcess) openIo() (err error) {
|
func (c *ContainerProcess) openIo() (err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Cleanup()
|
c.Cleanup()
|
||||||
|
@ -111,11 +111,11 @@ func (c *containerProcess) openIo() (err error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *containerProcess) GetEventsChannel() chan *types.Event {
|
func (c *ContainerProcess) GetEventsChannel() chan *types.Event {
|
||||||
return c.eventsCh
|
return c.eventsCh
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *containerProcess) GetNextEvent() *types.Event {
|
func (c *ContainerProcess) GetNextEvent() *types.Event {
|
||||||
if c.hasExited {
|
if c.hasExited {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -131,16 +131,16 @@ func (c *containerProcess) GetNextEvent() *types.Event {
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *containerProcess) CloseStdin() error {
|
func (c *ContainerProcess) CloseStdin() error {
|
||||||
_, err := c.cs.grpcClient.UpdateProcess(context.Background(), &types.UpdateProcessRequest{
|
_, err := c.cs.grpcClient.UpdateProcess(context.Background(), &types.UpdateProcessRequest{
|
||||||
Id: c.containerId,
|
Id: c.containerID,
|
||||||
Pid: c.pid,
|
Pid: c.pid,
|
||||||
CloseStdin: true,
|
CloseStdin: true,
|
||||||
})
|
})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *containerProcess) Cleanup() {
|
func (c *ContainerProcess) Cleanup() {
|
||||||
for _, f := range []*os.File{
|
for _, f := range []*os.File{
|
||||||
c.io.stdinf,
|
c.io.stdinf,
|
||||||
c.io.stdoutf,
|
c.io.stdoutf,
|
||||||
|
@ -153,9 +153,9 @@ func (c *containerProcess) Cleanup() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewContainerProcess(cs *ContainerdSuite, bundle *Bundle, cid, pid string) (c *containerProcess, err error) {
|
func NewContainerProcess(cs *ContainerdSuite, bundle *Bundle, cid, pid string) (c *ContainerProcess, err error) {
|
||||||
c = &containerProcess{
|
c = &ContainerProcess{
|
||||||
containerId: cid,
|
containerID: cid,
|
||||||
pid: "init",
|
pid: "init",
|
||||||
bundle: bundle,
|
bundle: bundle,
|
||||||
eventsCh: make(chan *types.Event, 8),
|
eventsCh: make(chan *types.Event, 8),
|
||||||
|
@ -181,7 +181,7 @@ func NewContainerProcess(cs *ContainerdSuite, bundle *Bundle, cid, pid string) (
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *ContainerdSuite) StartContainerWithEventFilter(id, bundleName string, filter func(*types.Event)) (c *containerProcess, err error) {
|
func (cs *ContainerdSuite) StartContainerWithEventFilter(id, bundleName string, filter func(*types.Event)) (c *ContainerProcess, err error) {
|
||||||
bundle := GetBundle(bundleName)
|
bundle := GetBundle(bundleName)
|
||||||
if bundle == nil {
|
if bundle == nil {
|
||||||
return nil, fmt.Errorf("No such bundle '%s'", bundleName)
|
return nil, fmt.Errorf("No such bundle '%s'", bundleName)
|
||||||
|
@ -216,11 +216,11 @@ func (cs *ContainerdSuite) StartContainerWithEventFilter(id, bundleName string,
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *ContainerdSuite) StartContainer(id, bundleName string) (c *containerProcess, err error) {
|
func (cs *ContainerdSuite) StartContainer(id, bundleName string) (c *ContainerProcess, err error) {
|
||||||
return cs.StartContainerWithEventFilter(id, bundleName, nil)
|
return cs.StartContainerWithEventFilter(id, bundleName, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *ContainerdSuite) RunContainer(id, bundleName string) (c *containerProcess, err error) {
|
func (cs *ContainerdSuite) RunContainer(id, bundleName string) (c *ContainerProcess, err error) {
|
||||||
c, err = cs.StartContainer(id, bundleName)
|
c, err = cs.StartContainer(id, bundleName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -236,14 +236,14 @@ func (cs *ContainerdSuite) RunContainer(id, bundleName string) (c *containerProc
|
||||||
return c, err
|
return c, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *ContainerdSuite) AddProcessToContainer(init *containerProcess, pid, cwd string, env, args []string, uid, gid uint32) (c *containerProcess, err error) {
|
func (cs *ContainerdSuite) AddProcessToContainer(init *ContainerProcess, pid, cwd string, env, args []string, uid, gid uint32) (c *ContainerProcess, err error) {
|
||||||
c, err = NewContainerProcess(cs, init.bundle, init.containerId, pid)
|
c, err = NewContainerProcess(cs, init.bundle, init.containerID, pid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
pr := &types.AddProcessRequest{
|
pr := &types.AddProcessRequest{
|
||||||
Id: init.containerId,
|
Id: init.containerID,
|
||||||
Pid: pid,
|
Pid: pid,
|
||||||
Args: args,
|
Args: args,
|
||||||
Cwd: cwd,
|
Cwd: cwd,
|
||||||
|
|
|
@ -17,12 +17,12 @@ func (cs *ContainerdSuite) TestBusyboxTopExecEcho(t *check.C) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
initp *containerProcess
|
initp *ContainerProcess
|
||||||
echop *containerProcess
|
echop *ContainerProcess
|
||||||
)
|
)
|
||||||
|
|
||||||
containerId := "top"
|
containerID := "top"
|
||||||
initp, err = cs.StartContainer(containerId, bundleName)
|
initp, err = cs.StartContainer(containerID, bundleName)
|
||||||
t.Assert(err, checker.Equals, nil)
|
t.Assert(err, checker.Equals, nil)
|
||||||
|
|
||||||
echop, err = cs.AddProcessToContainer(initp, "echo", "/", []string{"PATH=/bin"}, []string{"sh", "-c", "echo -n Ay Caramba! ; exit 1"}, 0, 0)
|
echop, err = cs.AddProcessToContainer(initp, "echo", "/", []string{"PATH=/bin"}, []string{"sh", "-c", "echo -n Ay Caramba! ; exit 1"}, 0, 0)
|
||||||
|
@ -31,19 +31,19 @@ func (cs *ContainerdSuite) TestBusyboxTopExecEcho(t *check.C) {
|
||||||
for _, evt := range []types.Event{
|
for _, evt := range []types.Event{
|
||||||
{
|
{
|
||||||
Type: "start-container",
|
Type: "start-container",
|
||||||
Id: containerId,
|
Id: containerID,
|
||||||
Status: 0,
|
Status: 0,
|
||||||
Pid: "",
|
Pid: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Type: "start-process",
|
Type: "start-process",
|
||||||
Id: containerId,
|
Id: containerID,
|
||||||
Status: 0,
|
Status: 0,
|
||||||
Pid: "echo",
|
Pid: "echo",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Type: "exit",
|
Type: "exit",
|
||||||
Id: containerId,
|
Id: containerID,
|
||||||
Status: 1,
|
Status: 1,
|
||||||
Pid: "echo",
|
Pid: "echo",
|
||||||
},
|
},
|
||||||
|
@ -66,35 +66,35 @@ func (cs *ContainerdSuite) TestBusyboxTopExecTop(t *check.C) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
initp *containerProcess
|
initp *ContainerProcess
|
||||||
)
|
)
|
||||||
|
|
||||||
containerId := "top"
|
containerID := "top"
|
||||||
initp, err = cs.StartContainer(containerId, bundleName)
|
initp, err = cs.StartContainer(containerID, bundleName)
|
||||||
t.Assert(err, checker.Equals, nil)
|
t.Assert(err, checker.Equals, nil)
|
||||||
|
|
||||||
execId := "top1"
|
execID := "top1"
|
||||||
_, err = cs.AddProcessToContainer(initp, execId, "/", []string{"PATH=/usr/bin"}, []string{"top"}, 0, 0)
|
_, err = cs.AddProcessToContainer(initp, execID, "/", []string{"PATH=/usr/bin"}, []string{"top"}, 0, 0)
|
||||||
t.Assert(err, checker.Equals, nil)
|
t.Assert(err, checker.Equals, nil)
|
||||||
|
|
||||||
for idx, evt := range []types.Event{
|
for idx, evt := range []types.Event{
|
||||||
{
|
{
|
||||||
Type: "start-container",
|
Type: "start-container",
|
||||||
Id: containerId,
|
Id: containerID,
|
||||||
Status: 0,
|
Status: 0,
|
||||||
Pid: "",
|
Pid: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Type: "start-process",
|
Type: "start-process",
|
||||||
Id: containerId,
|
Id: containerID,
|
||||||
Status: 0,
|
Status: 0,
|
||||||
Pid: execId,
|
Pid: execID,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Type: "exit",
|
Type: "exit",
|
||||||
Id: containerId,
|
Id: containerID,
|
||||||
Status: 137,
|
Status: 137,
|
||||||
Pid: execId,
|
Pid: execID,
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
ch := initp.GetEventsChannel()
|
ch := initp.GetEventsChannel()
|
||||||
|
@ -103,7 +103,7 @@ func (cs *ContainerdSuite) TestBusyboxTopExecTop(t *check.C) {
|
||||||
t.Assert(*e, checker.Equals, evt)
|
t.Assert(*e, checker.Equals, evt)
|
||||||
if idx == 1 {
|
if idx == 1 {
|
||||||
// Process Started, kill it
|
// Process Started, kill it
|
||||||
cs.SignalContainerProcess(containerId, "top1", uint32(syscall.SIGKILL))
|
cs.SignalContainerProcess(containerID, "top1", uint32(syscall.SIGKILL))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,39 +126,39 @@ func (cs *ContainerdSuite) TestBusyboxTopExecTopKillInit(t *check.C) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
initp *containerProcess
|
initp *ContainerProcess
|
||||||
)
|
)
|
||||||
|
|
||||||
containerId := "top"
|
containerID := "top"
|
||||||
initp, err = cs.StartContainer(containerId, bundleName)
|
initp, err = cs.StartContainer(containerID, bundleName)
|
||||||
t.Assert(err, checker.Equals, nil)
|
t.Assert(err, checker.Equals, nil)
|
||||||
|
|
||||||
execId := "top1"
|
execID := "top1"
|
||||||
_, err = cs.AddProcessToContainer(initp, execId, "/", []string{"PATH=/usr/bin"}, []string{"top"}, 0, 0)
|
_, err = cs.AddProcessToContainer(initp, execID, "/", []string{"PATH=/usr/bin"}, []string{"top"}, 0, 0)
|
||||||
t.Assert(err, checker.Equals, nil)
|
t.Assert(err, checker.Equals, nil)
|
||||||
|
|
||||||
for idx, evt := range []types.Event{
|
for idx, evt := range []types.Event{
|
||||||
{
|
{
|
||||||
Type: "start-container",
|
Type: "start-container",
|
||||||
Id: containerId,
|
Id: containerID,
|
||||||
Status: 0,
|
Status: 0,
|
||||||
Pid: "",
|
Pid: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Type: "start-process",
|
Type: "start-process",
|
||||||
Id: containerId,
|
Id: containerID,
|
||||||
Status: 0,
|
Status: 0,
|
||||||
Pid: execId,
|
Pid: execID,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Type: "exit",
|
Type: "exit",
|
||||||
Id: containerId,
|
Id: containerID,
|
||||||
Status: 137,
|
Status: 137,
|
||||||
Pid: execId,
|
Pid: execID,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Type: "exit",
|
Type: "exit",
|
||||||
Id: containerId,
|
Id: containerID,
|
||||||
Status: 143,
|
Status: 143,
|
||||||
Pid: "init",
|
Pid: "init",
|
||||||
},
|
},
|
||||||
|
@ -169,7 +169,7 @@ func (cs *ContainerdSuite) TestBusyboxTopExecTopKillInit(t *check.C) {
|
||||||
t.Assert(*e, checker.Equals, evt)
|
t.Assert(*e, checker.Equals, evt)
|
||||||
if idx == 1 {
|
if idx == 1 {
|
||||||
// Process Started, kill it
|
// Process Started, kill it
|
||||||
cs.SignalContainerProcess(containerId, "init", uint32(syscall.SIGTERM))
|
cs.SignalContainerProcess(containerID, "init", uint32(syscall.SIGTERM))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,8 +79,8 @@ func (cs *ContainerdSuite) TestStartBusyboxLsEvents(t *check.C) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
containerId := "ls-events"
|
containerID := "ls-events"
|
||||||
c, err := cs.StartContainer(containerId, "busybox-ls")
|
c, err := cs.StartContainer(containerID, "busybox-ls")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -88,13 +88,13 @@ func (cs *ContainerdSuite) TestStartBusyboxLsEvents(t *check.C) {
|
||||||
for _, evt := range []types.Event{
|
for _, evt := range []types.Event{
|
||||||
{
|
{
|
||||||
Type: "start-container",
|
Type: "start-container",
|
||||||
Id: containerId,
|
Id: containerID,
|
||||||
Status: 0,
|
Status: 0,
|
||||||
Pid: "",
|
Pid: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Type: "exit",
|
Type: "exit",
|
||||||
Id: containerId,
|
Id: containerID,
|
||||||
Status: 0,
|
Status: 0,
|
||||||
Pid: "init",
|
Pid: "init",
|
||||||
},
|
},
|
||||||
|
@ -144,7 +144,7 @@ func (cs *ContainerdSuite) TestStartBusyboxTopKill(t *check.C) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
containerId := "top"
|
containerID := "top"
|
||||||
c, err := cs.StartContainer("top", bundleName)
|
c, err := cs.StartContainer("top", bundleName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -152,7 +152,7 @@ func (cs *ContainerdSuite) TestStartBusyboxTopKill(t *check.C) {
|
||||||
|
|
||||||
<-time.After(1 * time.Second)
|
<-time.After(1 * time.Second)
|
||||||
|
|
||||||
err = cs.KillContainer(containerId)
|
err = cs.KillContainer(containerID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -160,13 +160,13 @@ func (cs *ContainerdSuite) TestStartBusyboxTopKill(t *check.C) {
|
||||||
for _, evt := range []types.Event{
|
for _, evt := range []types.Event{
|
||||||
{
|
{
|
||||||
Type: "start-container",
|
Type: "start-container",
|
||||||
Id: containerId,
|
Id: containerID,
|
||||||
Status: 0,
|
Status: 0,
|
||||||
Pid: "",
|
Pid: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Type: "exit",
|
Type: "exit",
|
||||||
Id: containerId,
|
Id: containerID,
|
||||||
Status: 128 + uint32(syscall.SIGKILL),
|
Status: 128 + uint32(syscall.SIGKILL),
|
||||||
Pid: "init",
|
Pid: "init",
|
||||||
},
|
},
|
||||||
|
@ -189,7 +189,7 @@ func (cs *ContainerdSuite) TestStartBusyboxTopSignalSigterm(t *check.C) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
containerId := "top"
|
containerID := "top"
|
||||||
c, err := cs.StartContainer("top", bundleName)
|
c, err := cs.StartContainer("top", bundleName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -197,7 +197,7 @@ func (cs *ContainerdSuite) TestStartBusyboxTopSignalSigterm(t *check.C) {
|
||||||
|
|
||||||
<-time.After(1 * time.Second)
|
<-time.After(1 * time.Second)
|
||||||
|
|
||||||
err = cs.SignalContainer(containerId, uint32(syscall.SIGTERM))
|
err = cs.SignalContainer(containerID, uint32(syscall.SIGTERM))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -205,13 +205,13 @@ func (cs *ContainerdSuite) TestStartBusyboxTopSignalSigterm(t *check.C) {
|
||||||
for _, evt := range []types.Event{
|
for _, evt := range []types.Event{
|
||||||
{
|
{
|
||||||
Type: "start-container",
|
Type: "start-container",
|
||||||
Id: containerId,
|
Id: containerID,
|
||||||
Status: 0,
|
Status: 0,
|
||||||
Pid: "",
|
Pid: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Type: "exit",
|
Type: "exit",
|
||||||
Id: containerId,
|
Id: containerID,
|
||||||
Status: 128 + uint32(syscall.SIGTERM),
|
Status: 128 + uint32(syscall.SIGTERM),
|
||||||
Pid: "init",
|
Pid: "init",
|
||||||
},
|
},
|
||||||
|
@ -233,13 +233,13 @@ func (cs *ContainerdSuite) TestStartBusyboxTrapUSR1(t *check.C) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
containerId := "trap-usr1"
|
containerID := "trap-usr1"
|
||||||
c, err := cs.StartContainer(containerId, "busybox-trap-usr1")
|
c, err := cs.StartContainer(containerID, "busybox-trap-usr1")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := cs.SignalContainer(containerId, uint32(syscall.SIGUSR1)); err != nil {
|
if err := cs.SignalContainer(containerID, uint32(syscall.SIGUSR1)); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,36 +259,36 @@ func (cs *ContainerdSuite) TestStartBusyboxTopPauseResume(t *check.C) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
containerId := "top"
|
containerID := "top"
|
||||||
c, err := cs.StartContainer(containerId, bundleName)
|
c, err := cs.StartContainer(containerID, bundleName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := cs.PauseContainer(containerId); err != nil {
|
if err := cs.PauseContainer(containerID); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := cs.ResumeContainer(containerId); err != nil {
|
if err := cs.ResumeContainer(containerID); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, evt := range []types.Event{
|
for _, evt := range []types.Event{
|
||||||
{
|
{
|
||||||
Type: "start-container",
|
Type: "start-container",
|
||||||
Id: containerId,
|
Id: containerID,
|
||||||
Status: 0,
|
Status: 0,
|
||||||
Pid: "",
|
Pid: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Type: "pause",
|
Type: "pause",
|
||||||
Id: containerId,
|
Id: containerID,
|
||||||
Status: 0,
|
Status: 0,
|
||||||
Pid: "",
|
Pid: "",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Type: "resume",
|
Type: "resume",
|
||||||
Id: containerId,
|
Id: containerID,
|
||||||
Status: 0,
|
Status: 0,
|
||||||
Pid: "",
|
Pid: "",
|
||||||
},
|
},
|
||||||
|
@ -323,8 +323,8 @@ func (cs *ContainerdSuite) TestRestart(t *check.C) {
|
||||||
totalCtr := 10
|
totalCtr := 10
|
||||||
|
|
||||||
for i := 0; i < totalCtr; i++ {
|
for i := 0; i < totalCtr; i++ {
|
||||||
containerId := fmt.Sprintf("top%d", i)
|
containerID := fmt.Sprintf("top%d", i)
|
||||||
c, err := cs.StartContainer(containerId, bundleName)
|
c, err := cs.StartContainer(containerID, bundleName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -333,7 +333,7 @@ func (cs *ContainerdSuite) TestRestart(t *check.C) {
|
||||||
|
|
||||||
t.Assert(*e, checker.Equals, types.Event{
|
t.Assert(*e, checker.Equals, types.Event{
|
||||||
Type: "start-container",
|
Type: "start-container",
|
||||||
Id: containerId,
|
Id: containerID,
|
||||||
Status: 0,
|
Status: 0,
|
||||||
Pid: "",
|
Pid: "",
|
||||||
Timestamp: e.Timestamp,
|
Timestamp: e.Timestamp,
|
||||||
|
@ -369,18 +369,18 @@ func (cs *ContainerdSuite) TestRestart(t *check.C) {
|
||||||
deathChans := make([]chan error, len(killedCtr))
|
deathChans := make([]chan error, len(killedCtr))
|
||||||
deathChansIdx := 0
|
deathChansIdx := 0
|
||||||
|
|
||||||
for i, _ := range killedCtr {
|
for i := range killedCtr {
|
||||||
ch := make(chan error, 1)
|
ch := make(chan error, 1)
|
||||||
deathChans[deathChansIdx] = ch
|
deathChans[deathChansIdx] = ch
|
||||||
deathChansIdx++
|
deathChansIdx++
|
||||||
syscall.Kill(int(containers[i].Pids[0]), syscall.SIGKILL)
|
syscall.Kill(int(containers[i].Pids[0]), syscall.SIGKILL)
|
||||||
|
|
||||||
// Filter to be notified of their death
|
// Filter to be notified of their death
|
||||||
containerId := fmt.Sprintf("top%d", i)
|
containerID := fmt.Sprintf("top%d", i)
|
||||||
f = func(event *types.Event) {
|
f = func(event *types.Event) {
|
||||||
expectedEvent := types.Event{
|
expectedEvent := types.Event{
|
||||||
Type: "exit",
|
Type: "exit",
|
||||||
Id: containerId,
|
Id: containerID,
|
||||||
Status: 137,
|
Status: 137,
|
||||||
Pid: "init",
|
Pid: "init",
|
||||||
}
|
}
|
||||||
|
@ -391,13 +391,13 @@ func (cs *ContainerdSuite) TestRestart(t *check.C) {
|
||||||
ch <- nil
|
ch <- nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cs.SetContainerEventFilter(containerId, f)
|
cs.SetContainerEventFilter(containerID, f)
|
||||||
}
|
}
|
||||||
|
|
||||||
cs.RestartDaemon(true)
|
cs.RestartDaemon(true)
|
||||||
|
|
||||||
// Ensure we got our events
|
// Ensure we got our events
|
||||||
for i, _ := range deathChans {
|
for i := range deathChans {
|
||||||
done := false
|
done := false
|
||||||
for done == false {
|
for done == false {
|
||||||
select {
|
select {
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
// +build linux
|
// +build linux
|
||||||
|
|
||||||
// http://man7.org/linux/man-pages/man2/prctl.2.html
|
// Package osutils provide access to the Get Child and Set Child prctl
|
||||||
|
// flags.
|
||||||
|
// See http://man7.org/linux/man-pages/man2/prctl.2.html
|
||||||
package osutils
|
package osutils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -8,6 +10,7 @@ import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// PR_SET_CHILD_SUBREAPER allows setting the child subreaper.
|
||||||
// If arg2 is nonzero, set the "child subreaper" attribute of the
|
// If arg2 is nonzero, set the "child subreaper" attribute of the
|
||||||
// calling process; if arg2 is zero, unset the attribute. When a
|
// calling process; if arg2 is zero, unset the attribute. When a
|
||||||
// process is marked as a child subreaper, all of the children
|
// process is marked as a child subreaper, all of the children
|
||||||
|
@ -19,16 +22,18 @@ import (
|
||||||
// nearest still living ancestor subreaper will receive a SIGCHLD
|
// nearest still living ancestor subreaper will receive a SIGCHLD
|
||||||
// signal and be able to wait(2) on the process to discover its
|
// signal and be able to wait(2) on the process to discover its
|
||||||
// termination status.
|
// termination status.
|
||||||
const PR_SET_CHILD_SUBREAPER = 36
|
const prSetChildSubreaper = 36
|
||||||
|
|
||||||
|
// PR_GET_CHILD_SUBREAPER allows retrieving the current child
|
||||||
|
// subreaper.
|
||||||
// Return the "child subreaper" setting of the caller, in the
|
// Return the "child subreaper" setting of the caller, in the
|
||||||
// location pointed to by (int *) arg2.
|
// location pointed to by (int *) arg2.
|
||||||
const PR_GET_CHILD_SUBREAPER = 37
|
const prGetChildSubreaper = 37
|
||||||
|
|
||||||
// GetSubreaper returns the subreaper setting for the calling process
|
// GetSubreaper returns the subreaper setting for the calling process
|
||||||
func GetSubreaper() (int, error) {
|
func GetSubreaper() (int, error) {
|
||||||
var i uintptr
|
var i uintptr
|
||||||
if _, _, err := syscall.RawSyscall(syscall.SYS_PRCTL, PR_GET_CHILD_SUBREAPER, uintptr(unsafe.Pointer(&i)), 0); err != 0 {
|
if _, _, err := syscall.RawSyscall(syscall.SYS_PRCTL, prGetChildSubreaper, uintptr(unsafe.Pointer(&i)), 0); err != 0 {
|
||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
return int(i), nil
|
return int(i), nil
|
||||||
|
@ -36,7 +41,7 @@ func GetSubreaper() (int, error) {
|
||||||
|
|
||||||
// SetSubreaper sets the value i as the subreaper setting for the calling process
|
// SetSubreaper sets the value i as the subreaper setting for the calling process
|
||||||
func SetSubreaper(i int) error {
|
func SetSubreaper(i int) error {
|
||||||
if _, _, err := syscall.RawSyscall(syscall.SYS_PRCTL, PR_SET_CHILD_SUBREAPER, uintptr(i), 0); err != 0 {
|
if _, _, err := syscall.RawSyscall(syscall.SYS_PRCTL, prSetChildSubreaper, uintptr(i), 0); err != 0 {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
//Solaris TODO
|
//Solaris TODO
|
||||||
|
|
||||||
// GetSubreaper returns the subreaper setting for the calling process
|
// GetSubreaper returns the subreaper setting for the calling process
|
||||||
func GetSubreaper() (int, error) {
|
func GetSubreaper() (int, error) {
|
||||||
return 0, errors.New("osutils GetSubreaper not implemented on Solaris")
|
return 0, errors.New("osutils GetSubreaper not implemented on Solaris")
|
||||||
|
|
|
@ -16,6 +16,7 @@ import (
|
||||||
ocs "github.com/opencontainers/runtime-spec/specs-go"
|
ocs "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Container defines the operations allowed on a container
|
||||||
type Container interface {
|
type Container interface {
|
||||||
// ID returns the container ID
|
// ID returns the container ID
|
||||||
ID() string
|
ID() string
|
||||||
|
@ -60,6 +61,7 @@ type Container interface {
|
||||||
Status() (State, error)
|
Status() (State, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OOM wraps a container OOM.
|
||||||
type OOM interface {
|
type OOM interface {
|
||||||
io.Closer
|
io.Closer
|
||||||
FD() int
|
FD() int
|
||||||
|
@ -68,12 +70,15 @@ type OOM interface {
|
||||||
Removed() bool
|
Removed() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Stdio holds the path to the 3 pipes used for the standard ios.
|
||||||
type Stdio struct {
|
type Stdio struct {
|
||||||
Stdin string
|
Stdin string
|
||||||
Stdout string
|
Stdout string
|
||||||
Stderr string
|
Stderr string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewStdio wraps the given standard io path into an Stdio struct.
|
||||||
|
// If a given parameter is the empty string, it is replaced by "/dev/null"
|
||||||
func NewStdio(stdin, stdout, stderr string) Stdio {
|
func NewStdio(stdin, stdout, stderr string) Stdio {
|
||||||
for _, s := range []*string{
|
for _, s := range []*string{
|
||||||
&stdin, &stdout, &stderr,
|
&stdin, &stdout, &stderr,
|
||||||
|
@ -89,6 +94,7 @@ func NewStdio(stdin, stdout, stderr string) Stdio {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ContainerOpts keeps the options passed at container creation
|
||||||
type ContainerOpts struct {
|
type ContainerOpts struct {
|
||||||
Root string
|
Root string
|
||||||
ID string
|
ID string
|
||||||
|
@ -136,6 +142,7 @@ func New(opts ContainerOpts) (Container, error) {
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load return a new container from the matchin state file on disk.
|
||||||
func Load(root, id string, timeout time.Duration) (Container, error) {
|
func Load(root, id string, timeout time.Duration) (Container, error) {
|
||||||
var s state
|
var s state
|
||||||
f, err := os.Open(filepath.Join(root, id, StateFile))
|
f, err := os.Open(filepath.Join(root, id, StateFile))
|
||||||
|
@ -355,7 +362,7 @@ func (c *container) Checkpoint(cpt Checkpoint, checkpointDir string) error {
|
||||||
if cpt.Shell {
|
if cpt.Shell {
|
||||||
add("--shell-job")
|
add("--shell-job")
|
||||||
}
|
}
|
||||||
if cpt.Tcp {
|
if cpt.TCP {
|
||||||
add("--tcp-established")
|
add("--tcp-established")
|
||||||
}
|
}
|
||||||
if cpt.UnixSockets {
|
if cpt.UnixSockets {
|
||||||
|
|
|
@ -15,6 +15,7 @@ import (
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Process holds the operation allowed on a container's process
|
||||||
type Process interface {
|
type Process interface {
|
||||||
io.Closer
|
io.Closer
|
||||||
|
|
||||||
|
|
|
@ -8,15 +8,17 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrNotChildProcess = errors.New("containerd: not a child process for container")
|
// ErrContainerExited is returned when access to an exited
|
||||||
ErrInvalidContainerType = errors.New("containerd: invalid container type for runtime")
|
// container is attempted
|
||||||
ErrCheckpointNotExists = errors.New("containerd: checkpoint does not exist for container")
|
ErrContainerExited = errors.New("containerd: container has exited")
|
||||||
ErrCheckpointExists = errors.New("containerd: checkpoint already exists")
|
// ErrProcessNotExited is returned when trying to retrive the exit
|
||||||
ErrContainerExited = errors.New("containerd: container has exited")
|
// status of an alive process
|
||||||
ErrTerminalsNotSupported = errors.New("containerd: terminals are not supported for runtime")
|
ErrProcessNotExited = errors.New("containerd: process has not exited")
|
||||||
ErrProcessNotExited = errors.New("containerd: process has not exited")
|
// ErrContainerNotStarted is returned when a container fails to
|
||||||
ErrProcessExited = errors.New("containerd: process has exited")
|
// start without error from the shim or the OCI runtime
|
||||||
ErrContainerNotStarted = errors.New("containerd: container not started")
|
ErrContainerNotStarted = errors.New("containerd: container not started")
|
||||||
|
// ErrContainerStartTimeout is returned if a container takes too
|
||||||
|
// long to start
|
||||||
ErrContainerStartTimeout = errors.New("containerd: container did not start before the specified timeout")
|
ErrContainerStartTimeout = errors.New("containerd: container did not start before the specified timeout")
|
||||||
|
|
||||||
errNoPidFile = errors.New("containerd: no process pid file found")
|
errNoPidFile = errors.New("containerd: no process pid file found")
|
||||||
|
@ -25,20 +27,30 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ExitFile = "exit"
|
// ExitFile holds the name of the pipe used to monitor process
|
||||||
|
// exit
|
||||||
|
ExitFile = "exit"
|
||||||
|
// ExitStatusFile holds the name of the file where the container
|
||||||
|
// exit code is to be written
|
||||||
ExitStatusFile = "exitStatus"
|
ExitStatusFile = "exitStatus"
|
||||||
StateFile = "state.json"
|
// StateFile holds the name of the file where the container state
|
||||||
ControlFile = "control"
|
// is written
|
||||||
InitProcessID = "init"
|
StateFile = "state.json"
|
||||||
|
// ControlFile holds the name of the pipe used to control the shim
|
||||||
|
ControlFile = "control"
|
||||||
|
// InitProcessID holds the special ID used for the very first
|
||||||
|
// container's process
|
||||||
|
InitProcessID = "init"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Checkpoint holds information regarding a container checkpoint
|
||||||
type Checkpoint struct {
|
type Checkpoint struct {
|
||||||
// Timestamp is the time that checkpoint happened
|
// Timestamp is the time that checkpoint happened
|
||||||
Created time.Time `json:"created"`
|
Created time.Time `json:"created"`
|
||||||
// Name is the name of the checkpoint
|
// Name is the name of the checkpoint
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
// Tcp checkpoints open tcp connections
|
// TCP checkpoints open tcp connections
|
||||||
Tcp bool `json:"tcp"`
|
TCP bool `json:"tcp"`
|
||||||
// UnixSockets persists unix sockets in the checkpoint
|
// UnixSockets persists unix sockets in the checkpoint
|
||||||
UnixSockets bool `json:"unixSockets"`
|
UnixSockets bool `json:"unixSockets"`
|
||||||
// Shell persists tty sessions in the checkpoint
|
// Shell persists tty sessions in the checkpoint
|
||||||
|
@ -53,8 +65,11 @@ type PlatformProcessState struct {
|
||||||
RootUID int `json:"rootUID"`
|
RootUID int `json:"rootUID"`
|
||||||
RootGID int `json:"rootGID"`
|
RootGID int `json:"rootGID"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// State represents a container state
|
||||||
type State string
|
type State string
|
||||||
|
|
||||||
|
// Resource regroups the various container limits that can be updated
|
||||||
type Resource struct {
|
type Resource struct {
|
||||||
CPUShares int64
|
CPUShares int64
|
||||||
BlkioWeight uint16
|
BlkioWeight uint16
|
||||||
|
@ -68,6 +83,7 @@ type Resource struct {
|
||||||
MemorySwap int64
|
MemorySwap int64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Possible container states
|
||||||
const (
|
const (
|
||||||
Paused = State("paused")
|
Paused = State("paused")
|
||||||
Stopped = State("stopped")
|
Stopped = State("stopped")
|
||||||
|
@ -86,6 +102,8 @@ type state struct {
|
||||||
NoPivotRoot bool `json:"noPivotRoot"`
|
NoPivotRoot bool `json:"noPivotRoot"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ProcessState holds the process OCI specs along with various fields
|
||||||
|
// required by containerd
|
||||||
type ProcessState struct {
|
type ProcessState struct {
|
||||||
specs.ProcessSpec
|
specs.ProcessSpec
|
||||||
Exec bool `json:"exec"`
|
Exec bool `json:"exec"`
|
||||||
|
|
|
@ -2,22 +2,25 @@ package runtime
|
||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
|
// Stat holds a container statistics
|
||||||
type Stat struct {
|
type Stat struct {
|
||||||
// Timestamp is the time that the statistics where collected
|
// Timestamp is the time that the statistics where collected
|
||||||
Timestamp time.Time
|
Timestamp time.Time
|
||||||
Cpu Cpu `json:"cpu"`
|
CPU CPU `json:"cpu"`
|
||||||
Memory Memory `json:"memory"`
|
Memory Memory `json:"memory"`
|
||||||
Pids Pids `json:"pids"`
|
Pids Pids `json:"pids"`
|
||||||
Blkio Blkio `json:"blkio"`
|
Blkio Blkio `json:"blkio"`
|
||||||
Hugetlb map[string]Hugetlb `json:"hugetlb"`
|
Hugetlb map[string]Hugetlb `json:"hugetlb"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hugetlb holds information regarding a container huge tlb usage
|
||||||
type Hugetlb struct {
|
type Hugetlb struct {
|
||||||
Usage uint64 `json:"usage,omitempty"`
|
Usage uint64 `json:"usage,omitempty"`
|
||||||
Max uint64 `json:"max,omitempty"`
|
Max uint64 `json:"max,omitempty"`
|
||||||
Failcnt uint64 `json:"failcnt"`
|
Failcnt uint64 `json:"failcnt"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BlkioEntry represents a single record for a Blkio stat
|
||||||
type BlkioEntry struct {
|
type BlkioEntry struct {
|
||||||
Major uint64 `json:"major,omitempty"`
|
Major uint64 `json:"major,omitempty"`
|
||||||
Minor uint64 `json:"minor,omitempty"`
|
Minor uint64 `json:"minor,omitempty"`
|
||||||
|
@ -25,6 +28,7 @@ type BlkioEntry struct {
|
||||||
Value uint64 `json:"value,omitempty"`
|
Value uint64 `json:"value,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Blkio regroups all the Blkio related stats
|
||||||
type Blkio struct {
|
type Blkio struct {
|
||||||
IoServiceBytesRecursive []BlkioEntry `json:"ioServiceBytesRecursive,omitempty"`
|
IoServiceBytesRecursive []BlkioEntry `json:"ioServiceBytesRecursive,omitempty"`
|
||||||
IoServicedRecursive []BlkioEntry `json:"ioServicedRecursive,omitempty"`
|
IoServicedRecursive []BlkioEntry `json:"ioServicedRecursive,omitempty"`
|
||||||
|
@ -36,18 +40,21 @@ type Blkio struct {
|
||||||
SectorsRecursive []BlkioEntry `json:"sectorsRecursive,omitempty"`
|
SectorsRecursive []BlkioEntry `json:"sectorsRecursive,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pids holds the stat of the pid usage of the machine
|
||||||
type Pids struct {
|
type Pids struct {
|
||||||
Current uint64 `json:"current,omitempty"`
|
Current uint64 `json:"current,omitempty"`
|
||||||
Limit uint64 `json:"limit,omitempty"`
|
Limit uint64 `json:"limit,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Throttling holds a cpu throttling information
|
||||||
type Throttling struct {
|
type Throttling struct {
|
||||||
Periods uint64 `json:"periods,omitempty"`
|
Periods uint64 `json:"periods,omitempty"`
|
||||||
ThrottledPeriods uint64 `json:"throttledPeriods,omitempty"`
|
ThrottledPeriods uint64 `json:"throttledPeriods,omitempty"`
|
||||||
ThrottledTime uint64 `json:"throttledTime,omitempty"`
|
ThrottledTime uint64 `json:"throttledTime,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type CpuUsage struct {
|
// CPUUsage holds information regarding cpu usage
|
||||||
|
type CPUUsage struct {
|
||||||
// Units: nanoseconds.
|
// Units: nanoseconds.
|
||||||
Total uint64 `json:"total,omitempty"`
|
Total uint64 `json:"total,omitempty"`
|
||||||
Percpu []uint64 `json:"percpu,omitempty"`
|
Percpu []uint64 `json:"percpu,omitempty"`
|
||||||
|
@ -55,11 +62,13 @@ type CpuUsage struct {
|
||||||
User uint64 `json:"user"`
|
User uint64 `json:"user"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Cpu struct {
|
// CPU regroups both a CPU usage and throttling information
|
||||||
Usage CpuUsage `json:"usage,omitempty"`
|
type CPU struct {
|
||||||
|
Usage CPUUsage `json:"usage,omitempty"`
|
||||||
Throttling Throttling `json:"throttling,omitempty"`
|
Throttling Throttling `json:"throttling,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MemoryEntry regroups statistic about a given type of memory
|
||||||
type MemoryEntry struct {
|
type MemoryEntry struct {
|
||||||
Limit uint64 `json:"limit"`
|
Limit uint64 `json:"limit"`
|
||||||
Usage uint64 `json:"usage,omitempty"`
|
Usage uint64 `json:"usage,omitempty"`
|
||||||
|
@ -67,6 +76,7 @@ type MemoryEntry struct {
|
||||||
Failcnt uint64 `json:"failcnt"`
|
Failcnt uint64 `json:"failcnt"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Memory holds information regarding the different type of memories available
|
||||||
type Memory struct {
|
type Memory struct {
|
||||||
Cache uint64 `json:"cache,omitempty"`
|
Cache uint64 `json:"cache,omitempty"`
|
||||||
Usage MemoryEntry `json:"usage,omitempty"`
|
Usage MemoryEntry `json:"usage,omitempty"`
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
package specs
|
package specs
|
||||||
|
|
||||||
import ocs "github.com/opencontainers/runtime-spec/specs-go"
|
import oci "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
|
||||||
type (
|
type (
|
||||||
ProcessSpec ocs.Process
|
// ProcessSpec aliases the platform process specs
|
||||||
Spec ocs.Spec
|
ProcessSpec oci.Process
|
||||||
Rlimit ocs.Rlimit
|
// Spec aliases the platform oci spec
|
||||||
|
Spec oci.Spec
|
||||||
|
// Rlimit aliases the platform resource limit
|
||||||
|
Rlimit oci.Rlimit
|
||||||
)
|
)
|
||||||
|
|
|
@ -7,6 +7,8 @@ import (
|
||||||
"github.com/docker/containerd/specs"
|
"github.com/docker/containerd/specs"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// AddProcessTask holds everything necessary to add a process to a
|
||||||
|
// container
|
||||||
type AddProcessTask struct {
|
type AddProcessTask struct {
|
||||||
baseTask
|
baseTask
|
||||||
ID string
|
ID string
|
||||||
|
|
|
@ -4,6 +4,7 @@ package supervisor
|
||||||
|
|
||||||
import "github.com/docker/containerd/runtime"
|
import "github.com/docker/containerd/runtime"
|
||||||
|
|
||||||
|
// CreateCheckpointTask holds needed parameters to create a new checkpoint
|
||||||
type CreateCheckpointTask struct {
|
type CreateCheckpointTask struct {
|
||||||
baseTask
|
baseTask
|
||||||
ID string
|
ID string
|
||||||
|
@ -19,6 +20,7 @@ func (s *Supervisor) createCheckpoint(t *CreateCheckpointTask) error {
|
||||||
return i.container.Checkpoint(*t.Checkpoint, t.CheckpointDir)
|
return i.container.Checkpoint(*t.Checkpoint, t.CheckpointDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeleteCheckpointTask holds needed parameters to delete a checkpoint
|
||||||
type DeleteCheckpointTask struct {
|
type DeleteCheckpointTask struct {
|
||||||
baseTask
|
baseTask
|
||||||
ID string
|
ID string
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"github.com/docker/containerd/runtime"
|
"github.com/docker/containerd/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// StartTask holds needed parameters to create a new container
|
||||||
type StartTask struct {
|
type StartTask struct {
|
||||||
baseTask
|
baseTask
|
||||||
ID string
|
ID string
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"github.com/docker/containerd/runtime"
|
"github.com/docker/containerd/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// DeleteTask holds needed parameters to remove a container
|
||||||
type DeleteTask struct {
|
type DeleteTask struct {
|
||||||
baseTask
|
baseTask
|
||||||
ID string
|
ID string
|
||||||
|
|
|
@ -3,14 +3,18 @@ package supervisor
|
||||||
import "errors"
|
import "errors"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// External errors
|
// ErrContainerNotFound is returned when the container ID passed
|
||||||
ErrTaskChanNil = errors.New("containerd: task channel is nil")
|
// for a given operation is invalid
|
||||||
ErrBundleNotFound = errors.New("containerd: bundle not found")
|
ErrContainerNotFound = errors.New("containerd: container not found")
|
||||||
ErrContainerNotFound = errors.New("containerd: container not found")
|
// ErrProcessNotFound is returned when the process ID passed for
|
||||||
ErrContainerExists = errors.New("containerd: container already exists")
|
// a given operation is invalid
|
||||||
ErrProcessNotFound = errors.New("containerd: process not found for container")
|
ErrProcessNotFound = errors.New("containerd: process not found for container")
|
||||||
|
// ErrUnknownContainerStatus is returned when the container status
|
||||||
|
// cannot be determined
|
||||||
ErrUnknownContainerStatus = errors.New("containerd: unknown container status ")
|
ErrUnknownContainerStatus = errors.New("containerd: unknown container status ")
|
||||||
ErrUnknownTask = errors.New("containerd: unknown task type")
|
// ErrUnknownTask is returned when an unknown Task type is
|
||||||
|
// scheduled (should never happen).
|
||||||
|
ErrUnknownTask = errors.New("containerd: unknown task type")
|
||||||
|
|
||||||
// Internal errors
|
// Internal errors
|
||||||
errShutdown = errors.New("containerd: supervisor is shutdown")
|
errShutdown = errors.New("containerd: supervisor is shutdown")
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"github.com/docker/containerd/runtime"
|
"github.com/docker/containerd/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ExitTask holds needed parameters to execute the exit task
|
||||||
type ExitTask struct {
|
type ExitTask struct {
|
||||||
baseTask
|
baseTask
|
||||||
Process runtime.Process
|
Process runtime.Process
|
||||||
|
@ -56,6 +57,7 @@ func (s *Supervisor) exit(t *ExitTask) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExecExitTask holds needed parameters to execute the exec exit task
|
||||||
type ExecExitTask struct {
|
type ExecExitTask struct {
|
||||||
baseTask
|
baseTask
|
||||||
ID string
|
ID string
|
||||||
|
|
|
@ -2,6 +2,8 @@ package supervisor
|
||||||
|
|
||||||
import "github.com/docker/containerd/runtime"
|
import "github.com/docker/containerd/runtime"
|
||||||
|
|
||||||
|
// GetContainersTask holds needed parameters to retrieve a list of
|
||||||
|
// containers
|
||||||
type GetContainersTask struct {
|
type GetContainersTask struct {
|
||||||
baseTask
|
baseTask
|
||||||
ID string
|
ID string
|
||||||
|
|
|
@ -4,11 +4,14 @@ package supervisor
|
||||||
|
|
||||||
import "github.com/cloudfoundry/gosigar"
|
import "github.com/cloudfoundry/gosigar"
|
||||||
|
|
||||||
|
// Machine holds the current machine cpu count and ram size
|
||||||
type Machine struct {
|
type Machine struct {
|
||||||
Cpus int
|
Cpus int
|
||||||
Memory int64
|
Memory int64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CollectMachineInformation returns information regarding the current
|
||||||
|
// machine (e.g. CPU count, RAM amount)
|
||||||
func CollectMachineInformation() (Machine, error) {
|
func CollectMachineInformation() (Machine, error) {
|
||||||
m := Machine{}
|
m := Machine{}
|
||||||
cpu := sigar.CpuList{}
|
cpu := sigar.CpuList{}
|
||||||
|
|
|
@ -3,18 +3,29 @@ package supervisor
|
||||||
import "github.com/rcrowley/go-metrics"
|
import "github.com/rcrowley/go-metrics"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ContainerCreateTimer = metrics.NewTimer()
|
// ContainerCreateTimer holds the metrics timer associated with container creation
|
||||||
ContainerDeleteTimer = metrics.NewTimer()
|
ContainerCreateTimer = metrics.NewTimer()
|
||||||
ContainerStartTimer = metrics.NewTimer()
|
// ContainerDeleteTimer holds the metrics timer associated with container deletion
|
||||||
ContainerStatsTimer = metrics.NewTimer()
|
ContainerDeleteTimer = metrics.NewTimer()
|
||||||
ContainersCounter = metrics.NewCounter()
|
// ContainerStartTimer holds the metrics timer associated with container start duration
|
||||||
|
ContainerStartTimer = metrics.NewTimer()
|
||||||
|
// ContainerStatsTimer holds the metrics timer associated with container stats generation
|
||||||
|
ContainerStatsTimer = metrics.NewTimer()
|
||||||
|
// ContainersCounter keeps track of the number of active containers
|
||||||
|
ContainersCounter = metrics.NewCounter()
|
||||||
|
// EventSubscriberCounter keeps track of the number of active event subscribers
|
||||||
EventSubscriberCounter = metrics.NewCounter()
|
EventSubscriberCounter = metrics.NewCounter()
|
||||||
TasksCounter = metrics.NewCounter()
|
// TasksCounter keeps track of the number of active supervisor tasks
|
||||||
ExecProcessTimer = metrics.NewTimer()
|
TasksCounter = metrics.NewCounter()
|
||||||
ExitProcessTimer = metrics.NewTimer()
|
// ExecProcessTimer holds the metrics timer associated with container exec
|
||||||
EpollFdCounter = metrics.NewCounter()
|
ExecProcessTimer = metrics.NewTimer()
|
||||||
|
// ExitProcessTimer holds the metrics timer associated with reporting container exit status
|
||||||
|
ExitProcessTimer = metrics.NewTimer()
|
||||||
|
// EpollFdCounter keeps trac of how many process are being monitored
|
||||||
|
EpollFdCounter = metrics.NewCounter()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Metrics return the list of all available metrics
|
||||||
func Metrics() map[string]interface{} {
|
func Metrics() map[string]interface{} {
|
||||||
return map[string]interface{}{
|
return map[string]interface{}{
|
||||||
"container-create-time": ContainerCreateTimer,
|
"container-create-time": ContainerCreateTimer,
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"github.com/docker/containerd/runtime"
|
"github.com/docker/containerd/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// NewMonitor starts a new process monitor and returns it
|
||||||
func NewMonitor() (*Monitor, error) {
|
func NewMonitor() (*Monitor, error) {
|
||||||
m := &Monitor{
|
m := &Monitor{
|
||||||
receivers: make(map[int]interface{}),
|
receivers: make(map[int]interface{}),
|
||||||
|
@ -24,6 +25,7 @@ func NewMonitor() (*Monitor, error) {
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Monitor represents a runtime.Process monitor
|
||||||
type Monitor struct {
|
type Monitor struct {
|
||||||
m sync.Mutex
|
m sync.Mutex
|
||||||
receivers map[int]interface{}
|
receivers map[int]interface{}
|
||||||
|
@ -32,14 +34,17 @@ type Monitor struct {
|
||||||
epollFd int
|
epollFd int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Exits returns the channel used to notify of a process exit
|
||||||
func (m *Monitor) Exits() chan runtime.Process {
|
func (m *Monitor) Exits() chan runtime.Process {
|
||||||
return m.exits
|
return m.exits
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OOMs returns the channel used to notify of a container exit due to OOM
|
||||||
func (m *Monitor) OOMs() chan string {
|
func (m *Monitor) OOMs() chan string {
|
||||||
return m.ooms
|
return m.ooms
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Monitor adds a process to the list of the one being monitored
|
||||||
func (m *Monitor) Monitor(p runtime.Process) error {
|
func (m *Monitor) Monitor(p runtime.Process) error {
|
||||||
m.m.Lock()
|
m.m.Lock()
|
||||||
defer m.m.Unlock()
|
defer m.m.Unlock()
|
||||||
|
@ -56,6 +61,7 @@ func (m *Monitor) Monitor(p runtime.Process) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MonitorOOM adds a container to the list of the ones monitored for OOM
|
||||||
func (m *Monitor) MonitorOOM(c runtime.Container) error {
|
func (m *Monitor) MonitorOOM(c runtime.Container) error {
|
||||||
m.m.Lock()
|
m.m.Lock()
|
||||||
defer m.m.Unlock()
|
defer m.m.Unlock()
|
||||||
|
@ -76,6 +82,7 @@ func (m *Monitor) MonitorOOM(c runtime.Container) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close cleans up resources allocated by NewMonitor()
|
||||||
func (m *Monitor) Close() error {
|
func (m *Monitor) Close() error {
|
||||||
return syscall.Close(m.epollFd)
|
return syscall.Close(m.epollFd)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// OOMTask holds needed parameters to report a container OOM
|
||||||
type OOMTask struct {
|
type OOMTask struct {
|
||||||
baseTask
|
baseTask
|
||||||
ID string
|
ID string
|
||||||
|
|
|
@ -2,6 +2,7 @@ package supervisor
|
||||||
|
|
||||||
import "os"
|
import "os"
|
||||||
|
|
||||||
|
// SignalTask holds needed parameters to signal a container
|
||||||
type SignalTask struct {
|
type SignalTask struct {
|
||||||
baseTask
|
baseTask
|
||||||
ID string
|
ID string
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"github.com/docker/containerd/runtime"
|
"github.com/docker/containerd/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// StatsTask holds needed parameters to retrieve a container statistics
|
||||||
type StatsTask struct {
|
type StatsTask struct {
|
||||||
baseTask
|
baseTask
|
||||||
ID string
|
ID string
|
||||||
|
|
|
@ -144,6 +144,7 @@ func readEventLog(s *Supervisor) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Supervisor represents a container supervisor
|
||||||
type Supervisor struct {
|
type Supervisor struct {
|
||||||
// stateDir is the directory on the system to store container runtime state information.
|
// stateDir is the directory on the system to store container runtime state information.
|
||||||
stateDir string
|
stateDir string
|
||||||
|
@ -179,6 +180,7 @@ func (s *Supervisor) Close() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Event represents a container event
|
||||||
type Event struct {
|
type Event struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"github.com/docker/containerd/runtime"
|
"github.com/docker/containerd/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// UpdateTask holds needed parameters to update a container resource constraints
|
||||||
type UpdateTask struct {
|
type UpdateTask struct {
|
||||||
baseTask
|
baseTask
|
||||||
ID string
|
ID string
|
||||||
|
@ -50,6 +51,8 @@ func (s *Supervisor) updateContainer(t *UpdateTask) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateProcessTask holds needed parameters to update a container
|
||||||
|
// process terminal size or close its stdin
|
||||||
type UpdateProcessTask struct {
|
type UpdateProcessTask struct {
|
||||||
baseTask
|
baseTask
|
||||||
ID string
|
ID string
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"github.com/docker/containerd/runtime"
|
"github.com/docker/containerd/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Worker interface
|
||||||
type Worker interface {
|
type Worker interface {
|
||||||
Start()
|
Start()
|
||||||
}
|
}
|
||||||
|
@ -22,6 +23,7 @@ type startTask struct {
|
||||||
StartResponse chan StartResponse
|
StartResponse chan StartResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewWorker return a new initialized worker
|
||||||
func NewWorker(s *Supervisor, wg *sync.WaitGroup) Worker {
|
func NewWorker(s *Supervisor, wg *sync.WaitGroup) Worker {
|
||||||
return &worker{
|
return &worker{
|
||||||
s: s,
|
s: s,
|
||||||
|
@ -34,6 +36,7 @@ type worker struct {
|
||||||
s *Supervisor
|
s *Supervisor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Start runs a loop in charge of starting new containers
|
||||||
func (w *worker) Start() {
|
func (w *worker) Start() {
|
||||||
defer w.wg.Done()
|
defer w.wg.Done()
|
||||||
for t := range w.s.startTasks {
|
for t := range w.s.startTasks {
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Output directory for testing and benchmark artifacts
|
// GetTestOutDir returns the output directory for testing and benchmark artifacts
|
||||||
func GetTestOutDir() string {
|
func GetTestOutDir() string {
|
||||||
out, _ := exec.Command("git", "rev-parse", "--show-toplevel").CombinedOutput()
|
out, _ := exec.Command("git", "rev-parse", "--show-toplevel").CombinedOutput()
|
||||||
repoRoot := string(out)
|
repoRoot := string(out)
|
||||||
|
@ -17,11 +17,18 @@ func GetTestOutDir() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ArchivesDir = filepath.Join("test-artifacts", "archives")
|
// ArchivesDir holds the location of the available rootfs
|
||||||
BundlesRoot = filepath.Join("test-artifacts", "oci-bundles")
|
ArchivesDir = filepath.Join("test-artifacts", "archives")
|
||||||
|
// BundlesRoot holds the location where OCI Bundles are stored
|
||||||
|
BundlesRoot = filepath.Join("test-artifacts", "oci-bundles")
|
||||||
|
// OutputDirFormat holds the standard format used when creating a
|
||||||
|
// new test output directory
|
||||||
OutputDirFormat = filepath.Join("test-artifacts", "runs", "%s")
|
OutputDirFormat = filepath.Join("test-artifacts", "runs", "%s")
|
||||||
|
// RefOciSpecsPath holds the path to the generic OCI config
|
||||||
RefOciSpecsPath = filepath.Join(BundlesRoot, "config.json")
|
RefOciSpecsPath = filepath.Join(BundlesRoot, "config.json")
|
||||||
StateDir = "/run/containerd-bench-test"
|
// StateDir holds the path to the directory used by the containerd
|
||||||
|
// started by tests
|
||||||
|
StateDir = "/run/containerd-bench-test"
|
||||||
)
|
)
|
||||||
|
|
||||||
// untarRootfs untars the given `source` tarPath into `destination/rootfs`
|
// untarRootfs untars the given `source` tarPath into `destination/rootfs`
|
||||||
|
@ -36,6 +43,7 @@ func untarRootfs(source string, destination string) error {
|
||||||
return tar.Run()
|
return tar.Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GenerateReferenceSpecs generates a default OCI specs via `runc spec`
|
||||||
func GenerateReferenceSpecs(destination string) error {
|
func GenerateReferenceSpecs(destination string) error {
|
||||||
if _, err := os.Stat(filepath.Join(destination, "config.json")); err == nil {
|
if _, err := os.Stat(filepath.Join(destination, "config.json")); err == nil {
|
||||||
return nil
|
return nil
|
||||||
|
@ -45,6 +53,7 @@ func GenerateReferenceSpecs(destination string) error {
|
||||||
return specs.Run()
|
return specs.Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateBundle generates a valid OCI bundle from the given rootfs
|
||||||
func CreateBundle(source, name string) error {
|
func CreateBundle(source, name string) error {
|
||||||
bundlePath := filepath.Join(BundlesRoot, name)
|
bundlePath := filepath.Join(BundlesRoot, name)
|
||||||
|
|
||||||
|
@ -55,6 +64,7 @@ func CreateBundle(source, name string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreateBusyboxBundle generates a bundle based on the busybox rootfs
|
||||||
func CreateBusyboxBundle(name string) error {
|
func CreateBusyboxBundle(name string) error {
|
||||||
return CreateBundle("busybox", name)
|
return CreateBundle("busybox", name)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,19 @@ package containerd
|
||||||
|
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
|
// VersionMajor holds the release major number
|
||||||
const VersionMajor = 0
|
const VersionMajor = 0
|
||||||
|
|
||||||
|
// VersionMinor holds the release minor number
|
||||||
const VersionMinor = 2
|
const VersionMinor = 2
|
||||||
|
|
||||||
|
// VersionPatch holds the release patch number
|
||||||
const VersionPatch = 0
|
const VersionPatch = 0
|
||||||
|
|
||||||
|
// Version holds the combination of major minor and patch as a string
|
||||||
|
// of format Major.Minor.Patch
|
||||||
var Version = fmt.Sprintf("%d.%d.%d", VersionMajor, VersionMinor, VersionPatch)
|
var Version = fmt.Sprintf("%d.%d.%d", VersionMajor, VersionMinor, VersionPatch)
|
||||||
|
|
||||||
|
// GitCommit is filled with the Git revision being used to build the
|
||||||
|
// program at linking time
|
||||||
var GitCommit = ""
|
var GitCommit = ""
|
||||||
|
|
Loading…
Reference in a new issue