2015-02-13 22:53:39 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2015-02-25 07:19:59 +00:00
|
|
|
"fmt"
|
2015-05-04 20:20:01 +00:00
|
|
|
"io/ioutil"
|
2015-02-27 22:18:11 +00:00
|
|
|
"net/http"
|
2015-09-18 17:41:12 +00:00
|
|
|
"os"
|
2015-02-25 07:19:59 +00:00
|
|
|
"os/exec"
|
2015-02-26 04:16:44 +00:00
|
|
|
"strings"
|
2015-07-06 14:27:17 +00:00
|
|
|
"time"
|
2015-04-18 16:46:47 +00:00
|
|
|
|
|
|
|
"github.com/go-check/check"
|
2015-02-13 22:53:39 +00:00
|
|
|
)
|
|
|
|
|
2015-07-22 12:59:24 +00:00
|
|
|
type testCondition func() bool
|
2015-02-13 22:53:39 +00:00
|
|
|
|
2015-07-22 12:59:24 +00:00
|
|
|
type testRequirement struct {
|
|
|
|
Condition testCondition
|
2015-02-13 22:53:39 +00:00
|
|
|
SkipMessage string
|
|
|
|
}
|
|
|
|
|
|
|
|
// List test requirements
|
|
|
|
var (
|
2015-08-27 22:08:00 +00:00
|
|
|
DaemonIsWindows = testRequirement{
|
|
|
|
func() bool { return daemonPlatform == "windows" },
|
|
|
|
"Test requires a Windows daemon",
|
|
|
|
}
|
|
|
|
DaemonIsLinux = testRequirement{
|
|
|
|
func() bool { return daemonPlatform == "linux" },
|
|
|
|
"Test requires a Linux daemon",
|
|
|
|
}
|
2016-06-15 17:18:55 +00:00
|
|
|
ExperimentalDaemon = testRequirement{
|
2016-10-06 14:09:54 +00:00
|
|
|
func() bool { return experimentalDaemon },
|
2016-06-15 17:18:55 +00:00
|
|
|
"Test requires an experimental daemon",
|
|
|
|
}
|
2016-04-07 21:41:40 +00:00
|
|
|
NotExperimentalDaemon = testRequirement{
|
2016-10-06 14:09:54 +00:00
|
|
|
func() bool { return !experimentalDaemon },
|
2016-04-07 21:41:40 +00:00
|
|
|
"Test requires a non experimental daemon",
|
|
|
|
}
|
2016-07-27 17:42:34 +00:00
|
|
|
IsAmd64 = testRequirement{
|
|
|
|
func() bool { return os.Getenv("DOCKER_ENGINE_GOARCH") == "amd64" },
|
|
|
|
"Test requires a daemon running on amd64",
|
|
|
|
}
|
2015-11-25 23:38:33 +00:00
|
|
|
NotArm = testRequirement{
|
2016-01-19 20:23:46 +00:00
|
|
|
func() bool { return os.Getenv("DOCKER_ENGINE_GOARCH") != "arm" },
|
2015-11-25 23:38:33 +00:00
|
|
|
"Test requires a daemon not running on ARM",
|
|
|
|
}
|
2016-07-04 10:09:46 +00:00
|
|
|
NotArm64 = testRequirement{
|
|
|
|
func() bool { return os.Getenv("DOCKER_ENGINE_GOARCH") != "arm64" },
|
|
|
|
"Test requires a daemon not running on arm64",
|
|
|
|
}
|
2016-02-09 23:02:18 +00:00
|
|
|
NotPpc64le = testRequirement{
|
|
|
|
func() bool { return os.Getenv("DOCKER_ENGINE_GOARCH") != "ppc64le" },
|
|
|
|
"Test requires a daemon not running on ppc64le",
|
|
|
|
}
|
2016-05-31 13:27:28 +00:00
|
|
|
NotS390X = testRequirement{
|
|
|
|
func() bool { return os.Getenv("DOCKER_ENGINE_GOARCH") != "s390x" },
|
|
|
|
"Test requires a daemon not running on s390x",
|
|
|
|
}
|
2015-07-22 12:59:24 +00:00
|
|
|
SameHostDaemon = testRequirement{
|
2015-02-13 22:53:39 +00:00
|
|
|
func() bool { return isLocalDaemon },
|
2015-11-06 11:15:42 +00:00
|
|
|
"Test requires docker daemon to run on the same machine as CLI",
|
2015-02-13 22:53:39 +00:00
|
|
|
}
|
2015-07-22 12:59:24 +00:00
|
|
|
UnixCli = testRequirement{
|
2015-02-20 09:37:27 +00:00
|
|
|
func() bool { return isUnixCli },
|
|
|
|
"Test requires posix utilities or functionality to run.",
|
|
|
|
}
|
2015-07-22 12:59:24 +00:00
|
|
|
ExecSupport = testRequirement{
|
2015-02-21 07:24:30 +00:00
|
|
|
func() bool { return supportsExec },
|
|
|
|
"Test requires 'docker exec' capabilities on the tested daemon.",
|
|
|
|
}
|
2015-07-22 12:59:24 +00:00
|
|
|
Network = testRequirement{
|
2015-02-27 22:18:11 +00:00
|
|
|
func() bool {
|
2015-07-06 14:27:17 +00:00
|
|
|
// Set a timeout on the GET at 15s
|
|
|
|
var timeout = time.Duration(15 * time.Second)
|
|
|
|
var url = "https://hub.docker.com"
|
|
|
|
|
|
|
|
client := http.Client{
|
|
|
|
Timeout: timeout,
|
|
|
|
}
|
|
|
|
|
|
|
|
resp, err := client.Get(url)
|
|
|
|
if err != nil && strings.Contains(err.Error(), "use of closed network connection") {
|
|
|
|
panic(fmt.Sprintf("Timeout for GET request on %s", url))
|
|
|
|
}
|
2015-02-27 22:18:11 +00:00
|
|
|
if resp != nil {
|
|
|
|
resp.Body.Close()
|
|
|
|
}
|
|
|
|
return err == nil
|
|
|
|
},
|
|
|
|
"Test requires network availability, environment variable set to none to run in a non-network enabled mode.",
|
|
|
|
}
|
2015-07-22 12:59:24 +00:00
|
|
|
Apparmor = testRequirement{
|
2015-05-04 20:20:01 +00:00
|
|
|
func() bool {
|
|
|
|
buf, err := ioutil.ReadFile("/sys/module/apparmor/parameters/enabled")
|
|
|
|
return err == nil && len(buf) > 1 && buf[0] == 'Y'
|
|
|
|
},
|
|
|
|
"Test requires apparmor is enabled.",
|
|
|
|
}
|
2015-07-22 12:59:24 +00:00
|
|
|
RegistryHosting = testRequirement{
|
2015-02-25 07:19:59 +00:00
|
|
|
func() bool {
|
|
|
|
// for now registry binary is built only if we're running inside
|
|
|
|
// container through `make test`. Figure that out by testing if
|
|
|
|
// registry binary is in PATH.
|
|
|
|
_, err := exec.LookPath(v2binary)
|
|
|
|
return err == nil
|
|
|
|
},
|
|
|
|
fmt.Sprintf("Test requires an environment that can host %s in the same host", v2binary),
|
|
|
|
}
|
2015-07-20 05:56:10 +00:00
|
|
|
NotaryHosting = testRequirement{
|
|
|
|
func() bool {
|
|
|
|
// for now notary binary is built only if we're running inside
|
|
|
|
// container through `make test`. Figure that out by testing if
|
|
|
|
// notary-server binary is in PATH.
|
2016-03-07 19:48:11 +00:00
|
|
|
_, err := exec.LookPath(notaryServerBinary)
|
2015-07-20 05:56:10 +00:00
|
|
|
return err == nil
|
|
|
|
},
|
2016-03-07 19:48:11 +00:00
|
|
|
fmt.Sprintf("Test requires an environment that can host %s in the same host", notaryServerBinary),
|
2015-07-20 05:56:10 +00:00
|
|
|
}
|
2016-03-11 22:11:35 +00:00
|
|
|
NotaryServerHosting = testRequirement{
|
|
|
|
func() bool {
|
|
|
|
// for now notary-server binary is built only if we're running inside
|
|
|
|
// container through `make test`. Figure that out by testing if
|
|
|
|
// notary-server binary is in PATH.
|
|
|
|
_, err := exec.LookPath(notaryServerBinary)
|
|
|
|
return err == nil
|
|
|
|
},
|
|
|
|
fmt.Sprintf("Test requires an environment that can host %s in the same host", notaryServerBinary),
|
|
|
|
}
|
2015-07-22 12:59:24 +00:00
|
|
|
NotOverlay = testRequirement{
|
2015-03-05 05:22:01 +00:00
|
|
|
func() bool {
|
2016-04-06 01:45:30 +00:00
|
|
|
return !strings.HasPrefix(daemonStorageDriver, "overlay")
|
2015-03-05 05:22:01 +00:00
|
|
|
},
|
|
|
|
"Test requires underlying root filesystem not be backed by overlay.",
|
|
|
|
}
|
2016-02-04 15:05:41 +00:00
|
|
|
|
|
|
|
Devicemapper = testRequirement{
|
|
|
|
func() bool {
|
2016-04-06 01:45:30 +00:00
|
|
|
return strings.HasPrefix(daemonStorageDriver, "devicemapper")
|
2016-02-04 15:05:41 +00:00
|
|
|
},
|
|
|
|
"Test requires underlying root filesystem to be backed by devicemapper.",
|
|
|
|
}
|
|
|
|
|
2015-07-22 12:59:24 +00:00
|
|
|
IPv6 = testRequirement{
|
2015-04-28 11:50:20 +00:00
|
|
|
func() bool {
|
|
|
|
cmd := exec.Command("test", "-f", "/proc/net/if_inet6")
|
|
|
|
|
|
|
|
if err := cmd.Run(); err != nil {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
},
|
|
|
|
"Test requires support for IPv6",
|
|
|
|
}
|
2016-08-09 16:14:38 +00:00
|
|
|
UserNamespaceROMount = testRequirement{
|
|
|
|
func() bool {
|
|
|
|
// quick case--userns not enabled in this test run
|
|
|
|
if os.Getenv("DOCKER_REMAP_ROOT") == "" {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
if _, _, err := dockerCmdWithError("run", "--rm", "--read-only", "busybox", "date"); err != nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
},
|
|
|
|
"Test cannot be run if user namespaces enabled but readonly mounts fail on this kernel.",
|
|
|
|
}
|
2016-03-03 00:58:49 +00:00
|
|
|
UserNamespaceInKernel = testRequirement{
|
|
|
|
func() bool {
|
|
|
|
if _, err := os.Stat("/proc/self/uid_map"); os.IsNotExist(err) {
|
|
|
|
/*
|
|
|
|
* This kernel-provided file only exists if user namespaces are
|
|
|
|
* supported
|
|
|
|
*/
|
|
|
|
return false
|
|
|
|
}
|
2016-03-09 19:20:41 +00:00
|
|
|
|
|
|
|
// We need extra check on redhat based distributions
|
|
|
|
if f, err := os.Open("/sys/module/user_namespace/parameters/enable"); err == nil {
|
2016-06-25 03:57:21 +00:00
|
|
|
defer f.Close()
|
2016-03-09 19:20:41 +00:00
|
|
|
b := make([]byte, 1)
|
|
|
|
_, _ = f.Read(b)
|
|
|
|
if string(b) == "N" {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2016-03-03 00:58:49 +00:00
|
|
|
return true
|
|
|
|
},
|
2016-03-09 19:20:41 +00:00
|
|
|
"Kernel must have user namespaces configured and enabled.",
|
2016-03-03 00:58:49 +00:00
|
|
|
}
|
2015-09-18 17:41:12 +00:00
|
|
|
NotUserNamespace = testRequirement{
|
|
|
|
func() bool {
|
|
|
|
root := os.Getenv("DOCKER_REMAP_ROOT")
|
|
|
|
if root != "" {
|
2015-10-10 02:09:02 +00:00
|
|
|
return false
|
2015-09-18 17:41:12 +00:00
|
|
|
}
|
2015-10-10 02:09:02 +00:00
|
|
|
return true
|
2015-09-18 17:41:12 +00:00
|
|
|
},
|
|
|
|
"Test cannot be run when remapping root",
|
|
|
|
}
|
2016-09-09 00:31:04 +00:00
|
|
|
IsPausable = testRequirement{
|
|
|
|
func() bool {
|
|
|
|
if daemonPlatform == "windows" {
|
|
|
|
return isolation == "hyperv"
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
},
|
|
|
|
"Test requires containers are pausable.",
|
|
|
|
}
|
|
|
|
NotPausable = testRequirement{
|
|
|
|
func() bool {
|
|
|
|
if daemonPlatform == "windows" {
|
|
|
|
return isolation == "process"
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
},
|
|
|
|
"Test requires containers are not pausable.",
|
|
|
|
}
|
2016-11-01 20:02:46 +00:00
|
|
|
IsolationIsHyperv = testRequirement{
|
|
|
|
func() bool {
|
|
|
|
return daemonPlatform == "windows" && isolation == "hyperv"
|
|
|
|
},
|
|
|
|
"Test requires a Windows daemon running default isolation mode of hyperv.",
|
|
|
|
}
|
|
|
|
IsolationIsProcess = testRequirement{
|
|
|
|
func() bool {
|
|
|
|
return daemonPlatform == "windows" && isolation == "process"
|
|
|
|
},
|
|
|
|
"Test requires a Windows daemon running default isolation mode of process.",
|
|
|
|
}
|
2015-02-13 22:53:39 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// testRequires checks if the environment satisfies the requirements
|
|
|
|
// for the test to run or skips the tests.
|
2015-07-22 12:59:24 +00:00
|
|
|
func testRequires(c *check.C, requirements ...testRequirement) {
|
2015-02-13 22:53:39 +00:00
|
|
|
for _, r := range requirements {
|
|
|
|
if !r.Condition() {
|
2015-04-18 16:46:47 +00:00
|
|
|
c.Skip(r.SkipMessage)
|
2015-02-13 22:53:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|