1package main 2 3import ( 4 "context" 5 "fmt" 6 "io/ioutil" 7 "net/http" 8 "os" 9 "os/exec" 10 "strconv" 11 "strings" 12 "testing" 13 "time" 14 15 "github.com/docker/docker/api/types" 16 "github.com/docker/docker/api/types/swarm" 17 "github.com/docker/docker/api/types/versions" 18 "github.com/docker/docker/client" 19 "github.com/docker/docker/integration-cli/requirement" 20 "github.com/docker/docker/testutil/registry" 21) 22 23func ArchitectureIsNot(arch string) bool { 24 return os.Getenv("DOCKER_ENGINE_GOARCH") != arch 25} 26 27func DaemonIsWindows() bool { 28 return testEnv.OSType == "windows" 29} 30 31func DaemonIsWindowsAtLeastBuild(buildNumber int) func() bool { 32 return func() bool { 33 if testEnv.OSType != "windows" { 34 return false 35 } 36 version := testEnv.DaemonInfo.KernelVersion 37 numVersion, _ := strconv.Atoi(strings.Split(version, " ")[1]) 38 return numVersion >= buildNumber 39 } 40} 41 42func DaemonIsLinux() bool { 43 return testEnv.OSType == "linux" 44} 45 46func MinimumAPIVersion(version string) func() bool { 47 return func() bool { 48 return versions.GreaterThanOrEqualTo(testEnv.DaemonAPIVersion(), version) 49 } 50} 51 52func OnlyDefaultNetworks() bool { 53 cli, err := client.NewClientWithOpts(client.FromEnv) 54 if err != nil { 55 return false 56 } 57 networks, err := cli.NetworkList(context.TODO(), types.NetworkListOptions{}) 58 if err != nil || len(networks) > 0 { 59 return false 60 } 61 return true 62} 63 64func IsAmd64() bool { 65 return os.Getenv("DOCKER_ENGINE_GOARCH") == "amd64" 66} 67 68func NotArm() bool { 69 return ArchitectureIsNot("arm") 70} 71 72func NotArm64() bool { 73 return ArchitectureIsNot("arm64") 74} 75 76func NotPpc64le() bool { 77 return ArchitectureIsNot("ppc64le") 78} 79 80func UnixCli() bool { 81 return isUnixCli 82} 83 84func Network() bool { 85 // Set a timeout on the GET at 15s 86 const timeout = 15 * time.Second 87 const url = "https://hub.docker.com" 88 89 client := http.Client{ 90 Timeout: timeout, 91 } 92 93 resp, err := client.Get(url) 94 if err != nil && strings.Contains(err.Error(), "use of closed network connection") { 95 panic(fmt.Sprintf("Timeout for GET request on %s", url)) 96 } 97 if resp != nil { 98 resp.Body.Close() 99 } 100 return err == nil 101} 102 103func Apparmor() bool { 104 if strings.HasPrefix(testEnv.DaemonInfo.OperatingSystem, "SUSE Linux Enterprise Server ") { 105 return false 106 } 107 buf, err := ioutil.ReadFile("/sys/module/apparmor/parameters/enabled") 108 return err == nil && len(buf) > 1 && buf[0] == 'Y' 109} 110 111func Devicemapper() bool { 112 return strings.HasPrefix(testEnv.DaemonInfo.Driver, "devicemapper") 113} 114 115func IPv6() bool { 116 cmd := exec.Command("test", "-f", "/proc/net/if_inet6") 117 return cmd.Run() != nil 118} 119 120func UserNamespaceROMount() bool { 121 // quick case--userns not enabled in this test run 122 if os.Getenv("DOCKER_REMAP_ROOT") == "" { 123 return true 124 } 125 if _, _, err := dockerCmdWithError("run", "--rm", "--read-only", "busybox", "date"); err != nil { 126 return false 127 } 128 return true 129} 130 131func NotUserNamespace() bool { 132 root := os.Getenv("DOCKER_REMAP_ROOT") 133 return root == "" 134} 135 136func UserNamespaceInKernel() bool { 137 if _, err := os.Stat("/proc/self/uid_map"); os.IsNotExist(err) { 138 /* 139 * This kernel-provided file only exists if user namespaces are 140 * supported 141 */ 142 return false 143 } 144 145 // We need extra check on redhat based distributions 146 if f, err := os.Open("/sys/module/user_namespace/parameters/enable"); err == nil { 147 defer f.Close() 148 b := make([]byte, 1) 149 _, _ = f.Read(b) 150 return string(b) != "N" 151 } 152 153 return true 154} 155 156func IsPausable() bool { 157 if testEnv.OSType == "windows" { 158 return testEnv.DaemonInfo.Isolation == "hyperv" 159 } 160 return true 161} 162 163func IsolationIs(expectedIsolation string) bool { 164 return testEnv.OSType == "windows" && string(testEnv.DaemonInfo.Isolation) == expectedIsolation 165} 166 167func IsolationIsHyperv() bool { 168 return IsolationIs("hyperv") 169} 170 171func IsolationIsProcess() bool { 172 return IsolationIs("process") 173} 174 175// RegistryHosting returns whether the host can host a registry (v2) or not 176func RegistryHosting() bool { 177 // for now registry binary is built only if we're running inside 178 // container through `make test`. Figure that out by testing if 179 // registry binary is in PATH. 180 _, err := exec.LookPath(registry.V2binary) 181 return err == nil 182} 183 184func SwarmInactive() bool { 185 return testEnv.DaemonInfo.Swarm.LocalNodeState == swarm.LocalNodeStateInactive 186} 187 188func TODOBuildkit() bool { 189 return os.Getenv("DOCKER_BUILDKIT") == "" 190} 191 192// testRequires checks if the environment satisfies the requirements 193// for the test to run or skips the tests. 194func testRequires(t *testing.T, requirements ...requirement.Test) { 195 t.Helper() 196 requirement.Is(t, requirements...) 197} 198