gopkg.in/docker/docker.v1@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  }