integration-cli/requirements.go
bc37c036
 package main
 
 import (
321874f3
 	"encoding/json"
e2aa8f0c
 	"fmt"
6f75dd85
 	"io/ioutil"
321874f3
 	"log"
5daa9260
 	"net/http"
ea3afdad
 	"os"
e2aa8f0c
 	"os/exec"
321874f3
 	"strings"
6e4c6da8
 	"time"
dc944ea7
 
 	"github.com/go-check/check"
bc37c036
 )
 
6b3c9281
 type testCondition func() bool
bc37c036
 
6b3c9281
 type testRequirement struct {
 	Condition   testCondition
bc37c036
 	SkipMessage string
 }
 
 // List test requirements
 var (
321874f3
 	daemonExecDriver string
 
cd18e7bb
 	DaemonIsWindows = testRequirement{
 		func() bool { return daemonPlatform == "windows" },
 		"Test requires a Windows daemon",
 	}
 	DaemonIsLinux = testRequirement{
 		func() bool { return daemonPlatform == "linux" },
 		"Test requires a Linux daemon",
 	}
6b3c9281
 	SameHostDaemon = testRequirement{
bc37c036
 		func() bool { return isLocalDaemon },
 		"Test requires docker daemon to runs on the same machine as CLI",
 	}
6b3c9281
 	UnixCli = testRequirement{
492a58f0
 		func() bool { return isUnixCli },
 		"Test requires posix utilities or functionality to run.",
 	}
6b3c9281
 	ExecSupport = testRequirement{
102e0611
 		func() bool { return supportsExec },
 		"Test requires 'docker exec' capabilities on the tested daemon.",
 	}
6b3c9281
 	Network = testRequirement{
5daa9260
 		func() bool {
6e4c6da8
 			// 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))
 			}
5daa9260
 			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.",
 	}
6b3c9281
 	Apparmor = testRequirement{
6f75dd85
 		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.",
 	}
6b3c9281
 	RegistryHosting = testRequirement{
e2aa8f0c
 		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),
 	}
58a1de9b
 	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.
 			_, err := exec.LookPath(notaryBinary)
 			return err == nil
 		},
 		fmt.Sprintf("Test requires an environment that can host %s in the same host", notaryBinary),
 	}
6b3c9281
 	NativeExecDriver = testRequirement{
321874f3
 		func() bool {
 			if daemonExecDriver == "" {
 				// get daemon info
c7845e27
 				status, body, err := sockRequest("GET", "/info", nil)
 				if err != nil || status != http.StatusOK {
321874f3
 					log.Fatalf("sockRequest failed for /info: %v", err)
 				}
 
 				type infoJSON struct {
 					ExecutionDriver string
 				}
 				var info infoJSON
 				if err = json.Unmarshal(body, &info); err != nil {
 					log.Fatalf("unable to unmarshal body: %v", err)
 				}
 
 				daemonExecDriver = info.ExecutionDriver
 			}
 
 			return strings.HasPrefix(daemonExecDriver, "native")
 		},
 		"Test requires the native (libcontainer) exec driver.",
 	}
6b3c9281
 	NotOverlay = testRequirement{
9057ca25
 		func() bool {
 			cmd := exec.Command("grep", "^overlay / overlay", "/proc/mounts")
 			if err := cmd.Run(); err != nil {
 				return true
 			}
 			return false
 		},
 		"Test requires underlying root filesystem not be backed by overlay.",
 	}
6b3c9281
 	IPv6 = testRequirement{
2dfb7f3b
 		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",
 	}
2c53643b
 	NotGCCGO = testRequirement{
 		func() bool {
 			out, err := exec.Command("go", "version").Output()
 			if err != nil && strings.Contains(string(out), "gccgo") {
 				return true
 			}
 			return false
 		},
 		"Test requires native Golang compiler instead of GCCGO",
 	}
ea3afdad
 	NotUserNamespace = testRequirement{
 		func() bool {
 			root := os.Getenv("DOCKER_REMAP_ROOT")
 			if root != "" {
930b27a8
 				return false
ea3afdad
 			}
930b27a8
 			return true
ea3afdad
 		},
 		"Test cannot be run when remapping root",
 	}
bc37c036
 )
 
 // testRequires checks if the environment satisfies the requirements
 // for the test to run or skips the tests.
6b3c9281
 func testRequires(c *check.C, requirements ...testRequirement) {
bc37c036
 	for _, r := range requirements {
 		if !r.Condition() {
dc944ea7
 			c.Skip(r.SkipMessage)
bc37c036
 		}
 	}
 }