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