2014-10-17 08:00:59 +08:00
|
|
|
package integration
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
2016-06-07 04:15:18 +08:00
|
|
|
"crypto/md5"
|
|
|
|
"encoding/hex"
|
2014-10-17 08:00:59 +08:00
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
|
|
|
"os/exec"
|
2015-04-05 04:29:50 +08:00
|
|
|
"path/filepath"
|
|
|
|
"runtime"
|
2015-02-07 13:12:27 +08:00
|
|
|
"strings"
|
2014-12-18 05:10:41 +08:00
|
|
|
"syscall"
|
2015-04-05 04:29:50 +08:00
|
|
|
"testing"
|
2016-06-07 04:15:18 +08:00
|
|
|
"time"
|
2014-10-17 08:00:59 +08:00
|
|
|
|
2015-06-22 10:29:59 +08:00
|
|
|
"github.com/opencontainers/runc/libcontainer"
|
|
|
|
"github.com/opencontainers/runc/libcontainer/configs"
|
2014-10-17 08:00:59 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
func newStdBuffers() *stdBuffers {
|
|
|
|
return &stdBuffers{
|
|
|
|
Stdin: bytes.NewBuffer(nil),
|
|
|
|
Stdout: bytes.NewBuffer(nil),
|
|
|
|
Stderr: bytes.NewBuffer(nil),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type stdBuffers struct {
|
|
|
|
Stdin *bytes.Buffer
|
|
|
|
Stdout *bytes.Buffer
|
|
|
|
Stderr *bytes.Buffer
|
|
|
|
}
|
|
|
|
|
2015-02-07 13:12:27 +08:00
|
|
|
func (b *stdBuffers) String() string {
|
|
|
|
s := []string{}
|
|
|
|
if b.Stderr != nil {
|
|
|
|
s = append(s, b.Stderr.String())
|
2014-10-17 08:00:59 +08:00
|
|
|
}
|
2015-02-07 13:12:27 +08:00
|
|
|
if b.Stdout != nil {
|
|
|
|
s = append(s, b.Stdout.String())
|
2014-10-17 08:00:59 +08:00
|
|
|
}
|
2015-02-07 13:12:27 +08:00
|
|
|
return strings.Join(s, "|")
|
2014-10-17 08:00:59 +08:00
|
|
|
}
|
|
|
|
|
2015-04-05 04:29:50 +08:00
|
|
|
// ok fails the test if an err is not nil.
|
|
|
|
func ok(t testing.TB, err error) {
|
|
|
|
if err != nil {
|
|
|
|
_, file, line, _ := runtime.Caller(1)
|
|
|
|
t.Fatalf("%s:%d: unexpected error: %s\n\n", filepath.Base(file), line, err.Error())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-21 01:10:10 +08:00
|
|
|
func waitProcess(p *libcontainer.Process, t *testing.T) {
|
|
|
|
_, file, line, _ := runtime.Caller(1)
|
|
|
|
status, err := p.Wait()
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("%s:%d: unexpected error: %s\n\n", filepath.Base(file), line, err.Error())
|
|
|
|
}
|
|
|
|
|
|
|
|
if !status.Success() {
|
|
|
|
t.Fatalf("%s:%d: unexpected status: %s\n\n", filepath.Base(file), line, status.String())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-19 16:08:06 +08:00
|
|
|
func newTestRoot() (string, error) {
|
|
|
|
dir, err := ioutil.TempDir("", "libcontainer")
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
if err := os.MkdirAll(dir, 0700); err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
return dir, nil
|
|
|
|
}
|
|
|
|
|
2016-12-19 23:38:56 +08:00
|
|
|
func newTestBundle() (string, error) {
|
|
|
|
dir, err := ioutil.TempDir("", "bundle")
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
if err := os.MkdirAll(dir, 0700); err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
return dir, nil
|
|
|
|
}
|
|
|
|
|
2015-02-04 09:44:58 +08:00
|
|
|
// newRootfs creates a new tmp directory and copies the busybox root filesystem
|
|
|
|
func newRootfs() (string, error) {
|
2014-10-17 08:00:59 +08:00
|
|
|
dir, err := ioutil.TempDir("", "")
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
if err := os.MkdirAll(dir, 0700); err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
if err := copyBusybox(dir); err != nil {
|
2015-07-25 22:23:56 +08:00
|
|
|
return "", err
|
2014-10-17 08:00:59 +08:00
|
|
|
}
|
|
|
|
return dir, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func remove(dir string) {
|
|
|
|
os.RemoveAll(dir)
|
|
|
|
}
|
|
|
|
|
|
|
|
// copyBusybox copies the rootfs for a busybox container created for the test image
|
|
|
|
// into the new directory for the specific test
|
|
|
|
func copyBusybox(dest string) error {
|
2017-11-01 17:52:05 +08:00
|
|
|
out, err := exec.Command("sh", "-c", fmt.Sprintf("cp -a /busybox/* %s/", dest)).CombinedOutput()
|
2014-10-17 08:00:59 +08:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("copy error %q: %q", err, out)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2015-02-17 05:09:00 +08:00
|
|
|
func newContainer(config *configs.Config) (libcontainer.Container, error) {
|
2016-06-07 04:15:18 +08:00
|
|
|
h := md5.New()
|
|
|
|
h.Write([]byte(time.Now().String()))
|
|
|
|
return newContainerWithName(hex.EncodeToString(h.Sum(nil)), config)
|
2015-09-14 08:35:22 +08:00
|
|
|
}
|
2015-05-01 23:27:04 +08:00
|
|
|
|
2015-09-14 08:35:22 +08:00
|
|
|
func newContainerWithName(name string, config *configs.Config) (libcontainer.Container, error) {
|
|
|
|
f := factory
|
2015-12-03 12:57:02 +08:00
|
|
|
if config.Cgroups != nil && config.Cgroups.Parent == "system.slice" {
|
2015-05-01 23:27:04 +08:00
|
|
|
f = systemdFactory
|
2015-04-03 13:15:06 +08:00
|
|
|
}
|
2015-09-14 08:35:22 +08:00
|
|
|
return f.Create(name, config)
|
2015-02-17 05:09:00 +08:00
|
|
|
}
|
|
|
|
|
2014-10-17 08:00:59 +08:00
|
|
|
// runContainer runs the container with the specific config and arguments
|
|
|
|
//
|
|
|
|
// buffers are returned containing the STDOUT and STDERR output for the run
|
|
|
|
// along with the exit code and any go error
|
2014-12-17 17:12:23 +08:00
|
|
|
func runContainer(config *configs.Config, console string, args ...string) (buffers *stdBuffers, exitCode int, err error) {
|
2015-02-17 05:09:00 +08:00
|
|
|
container, err := newContainer(config)
|
|
|
|
if err != nil {
|
2014-10-17 08:00:59 +08:00
|
|
|
return nil, -1, err
|
|
|
|
}
|
2015-02-17 05:09:00 +08:00
|
|
|
defer container.Destroy()
|
2014-10-17 08:00:59 +08:00
|
|
|
buffers = newStdBuffers()
|
2015-02-03 18:53:31 +08:00
|
|
|
process := &libcontainer.Process{
|
2016-01-15 07:21:36 +08:00
|
|
|
Cwd: "/",
|
2014-12-18 05:10:41 +08:00
|
|
|
Args: args,
|
2015-02-07 11:16:11 +08:00
|
|
|
Env: standardEnvironment,
|
2014-12-18 05:10:41 +08:00
|
|
|
Stdin: buffers.Stdin,
|
|
|
|
Stdout: buffers.Stdout,
|
|
|
|
Stderr: buffers.Stderr,
|
|
|
|
}
|
|
|
|
|
2016-05-28 04:13:11 +08:00
|
|
|
err = container.Run(process)
|
2014-12-18 05:10:41 +08:00
|
|
|
if err != nil {
|
2015-05-30 06:24:18 +08:00
|
|
|
return buffers, -1, err
|
2014-12-18 05:10:41 +08:00
|
|
|
}
|
2015-02-23 17:26:43 +08:00
|
|
|
ps, err := process.Wait()
|
2014-12-18 05:10:41 +08:00
|
|
|
if err != nil {
|
2015-05-30 06:24:18 +08:00
|
|
|
return buffers, -1, err
|
2014-12-18 05:10:41 +08:00
|
|
|
}
|
|
|
|
status := ps.Sys().(syscall.WaitStatus)
|
|
|
|
if status.Exited() {
|
|
|
|
exitCode = status.ExitStatus()
|
|
|
|
} else if status.Signaled() {
|
|
|
|
exitCode = -int(status.Signal())
|
|
|
|
} else {
|
2015-05-30 06:24:18 +08:00
|
|
|
return buffers, -1, err
|
2014-12-18 05:10:41 +08:00
|
|
|
}
|
2014-10-17 08:00:59 +08:00
|
|
|
return
|
|
|
|
}
|