github.com/vieux/docker@v0.6.3-0.20161004191708-e097c2a938c7/integration-cli/requirements.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "net/http" 7 "os" 8 "os/exec" 9 "strings" 10 "time" 11 12 "github.com/docker/docker/utils" 13 "github.com/go-check/check" 14 ) 15 16 type testCondition func() bool 17 18 type testRequirement struct { 19 Condition testCondition 20 SkipMessage string 21 } 22 23 // List test requirements 24 var ( 25 DaemonIsWindows = testRequirement{ 26 func() bool { return daemonPlatform == "windows" }, 27 "Test requires a Windows daemon", 28 } 29 DaemonIsLinux = testRequirement{ 30 func() bool { return daemonPlatform == "linux" }, 31 "Test requires a Linux daemon", 32 } 33 ExperimentalDaemon = testRequirement{ 34 func() bool { return utils.ExperimentalBuild() }, 35 "Test requires an experimental daemon", 36 } 37 NotExperimentalDaemon = testRequirement{ 38 func() bool { return !utils.ExperimentalBuild() }, 39 "Test requires a non experimental daemon", 40 } 41 IsAmd64 = testRequirement{ 42 func() bool { return os.Getenv("DOCKER_ENGINE_GOARCH") == "amd64" }, 43 "Test requires a daemon running on amd64", 44 } 45 NotArm = testRequirement{ 46 func() bool { return os.Getenv("DOCKER_ENGINE_GOARCH") != "arm" }, 47 "Test requires a daemon not running on ARM", 48 } 49 NotArm64 = testRequirement{ 50 func() bool { return os.Getenv("DOCKER_ENGINE_GOARCH") != "arm64" }, 51 "Test requires a daemon not running on arm64", 52 } 53 NotPpc64le = testRequirement{ 54 func() bool { return os.Getenv("DOCKER_ENGINE_GOARCH") != "ppc64le" }, 55 "Test requires a daemon not running on ppc64le", 56 } 57 NotS390X = testRequirement{ 58 func() bool { return os.Getenv("DOCKER_ENGINE_GOARCH") != "s390x" }, 59 "Test requires a daemon not running on s390x", 60 } 61 SameHostDaemon = testRequirement{ 62 func() bool { return isLocalDaemon }, 63 "Test requires docker daemon to run on the same machine as CLI", 64 } 65 UnixCli = testRequirement{ 66 func() bool { return isUnixCli }, 67 "Test requires posix utilities or functionality to run.", 68 } 69 ExecSupport = testRequirement{ 70 func() bool { return supportsExec }, 71 "Test requires 'docker exec' capabilities on the tested daemon.", 72 } 73 Network = testRequirement{ 74 func() bool { 75 // Set a timeout on the GET at 15s 76 var timeout = time.Duration(15 * time.Second) 77 var url = "https://hub.docker.com" 78 79 client := http.Client{ 80 Timeout: timeout, 81 } 82 83 resp, err := client.Get(url) 84 if err != nil && strings.Contains(err.Error(), "use of closed network connection") { 85 panic(fmt.Sprintf("Timeout for GET request on %s", url)) 86 } 87 if resp != nil { 88 resp.Body.Close() 89 } 90 return err == nil 91 }, 92 "Test requires network availability, environment variable set to none to run in a non-network enabled mode.", 93 } 94 Apparmor = testRequirement{ 95 func() bool { 96 buf, err := ioutil.ReadFile("/sys/module/apparmor/parameters/enabled") 97 return err == nil && len(buf) > 1 && buf[0] == 'Y' 98 }, 99 "Test requires apparmor is enabled.", 100 } 101 RegistryHosting = testRequirement{ 102 func() bool { 103 // for now registry binary is built only if we're running inside 104 // container through `make test`. Figure that out by testing if 105 // registry binary is in PATH. 106 _, err := exec.LookPath(v2binary) 107 return err == nil 108 }, 109 fmt.Sprintf("Test requires an environment that can host %s in the same host", v2binary), 110 } 111 NotaryHosting = testRequirement{ 112 func() bool { 113 // for now notary binary is built only if we're running inside 114 // container through `make test`. Figure that out by testing if 115 // notary-server binary is in PATH. 116 _, err := exec.LookPath(notaryServerBinary) 117 return err == nil 118 }, 119 fmt.Sprintf("Test requires an environment that can host %s in the same host", notaryServerBinary), 120 } 121 NotaryServerHosting = testRequirement{ 122 func() bool { 123 // for now notary-server binary is built only if we're running inside 124 // container through `make test`. Figure that out by testing if 125 // notary-server binary is in PATH. 126 _, err := exec.LookPath(notaryServerBinary) 127 return err == nil 128 }, 129 fmt.Sprintf("Test requires an environment that can host %s in the same host", notaryServerBinary), 130 } 131 NotOverlay = testRequirement{ 132 func() bool { 133 return !strings.HasPrefix(daemonStorageDriver, "overlay") 134 }, 135 "Test requires underlying root filesystem not be backed by overlay.", 136 } 137 138 Devicemapper = testRequirement{ 139 func() bool { 140 return strings.HasPrefix(daemonStorageDriver, "devicemapper") 141 }, 142 "Test requires underlying root filesystem to be backed by devicemapper.", 143 } 144 145 IPv6 = testRequirement{ 146 func() bool { 147 cmd := exec.Command("test", "-f", "/proc/net/if_inet6") 148 149 if err := cmd.Run(); err != nil { 150 return true 151 } 152 return false 153 }, 154 "Test requires support for IPv6", 155 } 156 UserNamespaceROMount = testRequirement{ 157 func() bool { 158 // quick case--userns not enabled in this test run 159 if os.Getenv("DOCKER_REMAP_ROOT") == "" { 160 return true 161 } 162 if _, _, err := dockerCmdWithError("run", "--rm", "--read-only", "busybox", "date"); err != nil { 163 return false 164 } 165 return true 166 }, 167 "Test cannot be run if user namespaces enabled but readonly mounts fail on this kernel.", 168 } 169 UserNamespaceInKernel = testRequirement{ 170 func() bool { 171 if _, err := os.Stat("/proc/self/uid_map"); os.IsNotExist(err) { 172 /* 173 * This kernel-provided file only exists if user namespaces are 174 * supported 175 */ 176 return false 177 } 178 179 // We need extra check on redhat based distributions 180 if f, err := os.Open("/sys/module/user_namespace/parameters/enable"); err == nil { 181 defer f.Close() 182 b := make([]byte, 1) 183 _, _ = f.Read(b) 184 if string(b) == "N" { 185 return false 186 } 187 return true 188 } 189 190 return true 191 }, 192 "Kernel must have user namespaces configured and enabled.", 193 } 194 NotUserNamespace = testRequirement{ 195 func() bool { 196 root := os.Getenv("DOCKER_REMAP_ROOT") 197 if root != "" { 198 return false 199 } 200 return true 201 }, 202 "Test cannot be run when remapping root", 203 } 204 ) 205 206 // testRequires checks if the environment satisfies the requirements 207 // for the test to run or skips the tests. 208 func testRequires(c *check.C, requirements ...testRequirement) { 209 for _, r := range requirements { 210 if !r.Condition() { 211 c.Skip(r.SkipMessage) 212 } 213 } 214 }