github.com/akerouanton/docker@v1.11.0-rc3/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  	NotArm = testRequirement{
    33  		func() bool { return os.Getenv("DOCKER_ENGINE_GOARCH") != "arm" },
    34  		"Test requires a daemon not running on ARM",
    35  	}
    36  	NotPpc64le = testRequirement{
    37  		func() bool { return os.Getenv("DOCKER_ENGINE_GOARCH") != "ppc64le" },
    38  		"Test requires a daemon not running on ppc64le",
    39  	}
    40  	SameHostDaemon = testRequirement{
    41  		func() bool { return isLocalDaemon },
    42  		"Test requires docker daemon to run on the same machine as CLI",
    43  	}
    44  	UnixCli = testRequirement{
    45  		func() bool { return isUnixCli },
    46  		"Test requires posix utilities or functionality to run.",
    47  	}
    48  	ExecSupport = testRequirement{
    49  		func() bool { return supportsExec },
    50  		"Test requires 'docker exec' capabilities on the tested daemon.",
    51  	}
    52  	Network = testRequirement{
    53  		func() bool {
    54  			// Set a timeout on the GET at 15s
    55  			var timeout = time.Duration(15 * time.Second)
    56  			var url = "https://hub.docker.com"
    57  
    58  			client := http.Client{
    59  				Timeout: timeout,
    60  			}
    61  
    62  			resp, err := client.Get(url)
    63  			if err != nil && strings.Contains(err.Error(), "use of closed network connection") {
    64  				panic(fmt.Sprintf("Timeout for GET request on %s", url))
    65  			}
    66  			if resp != nil {
    67  				resp.Body.Close()
    68  			}
    69  			return err == nil
    70  		},
    71  		"Test requires network availability, environment variable set to none to run in a non-network enabled mode.",
    72  	}
    73  	Apparmor = testRequirement{
    74  		func() bool {
    75  			buf, err := ioutil.ReadFile("/sys/module/apparmor/parameters/enabled")
    76  			return err == nil && len(buf) > 1 && buf[0] == 'Y'
    77  		},
    78  		"Test requires apparmor is enabled.",
    79  	}
    80  	RegistryHosting = testRequirement{
    81  		func() bool {
    82  			// for now registry binary is built only if we're running inside
    83  			// container through `make test`. Figure that out by testing if
    84  			// registry binary is in PATH.
    85  			_, err := exec.LookPath(v2binary)
    86  			return err == nil
    87  		},
    88  		fmt.Sprintf("Test requires an environment that can host %s in the same host", v2binary),
    89  	}
    90  	NotaryHosting = testRequirement{
    91  		func() bool {
    92  			// for now notary binary is built only if we're running inside
    93  			// container through `make test`. Figure that out by testing if
    94  			// notary-server binary is in PATH.
    95  			_, err := exec.LookPath(notaryServerBinary)
    96  			return err == nil
    97  		},
    98  		fmt.Sprintf("Test requires an environment that can host %s in the same host", notaryServerBinary),
    99  	}
   100  	NotaryServerHosting = testRequirement{
   101  		func() bool {
   102  			// for now notary-server binary is built only if we're running inside
   103  			// container through `make test`. Figure that out by testing if
   104  			// notary-server binary is in PATH.
   105  			_, err := exec.LookPath(notaryServerBinary)
   106  			return err == nil
   107  		},
   108  		fmt.Sprintf("Test requires an environment that can host %s in the same host", notaryServerBinary),
   109  	}
   110  	NotOverlay = testRequirement{
   111  		func() bool {
   112  			cmd := exec.Command("grep", "^overlay / overlay", "/proc/mounts")
   113  			if err := cmd.Run(); err != nil {
   114  				return true
   115  			}
   116  			return false
   117  		},
   118  		"Test requires underlying root filesystem not be backed by overlay.",
   119  	}
   120  
   121  	Devicemapper = testRequirement{
   122  		func() bool {
   123  			cmd := exec.Command("grep", "^devicemapper / devicemapper", "/proc/mounts")
   124  			if err := cmd.Run(); err != nil {
   125  				return false
   126  			}
   127  			return true
   128  		},
   129  		"Test requires underlying root filesystem to be backed by devicemapper.",
   130  	}
   131  
   132  	IPv6 = testRequirement{
   133  		func() bool {
   134  			cmd := exec.Command("test", "-f", "/proc/net/if_inet6")
   135  
   136  			if err := cmd.Run(); err != nil {
   137  				return true
   138  			}
   139  			return false
   140  		},
   141  		"Test requires support for IPv6",
   142  	}
   143  	NotGCCGO = testRequirement{
   144  		func() bool {
   145  			out, err := exec.Command("go", "version").Output()
   146  			if err == nil && strings.Contains(string(out), "gccgo") {
   147  				return false
   148  			}
   149  			return true
   150  		},
   151  		"Test requires native Golang compiler instead of GCCGO",
   152  	}
   153  	UserNamespaceInKernel = testRequirement{
   154  		func() bool {
   155  			if _, err := os.Stat("/proc/self/uid_map"); os.IsNotExist(err) {
   156  				/*
   157  				 * This kernel-provided file only exists if user namespaces are
   158  				 * supported
   159  				 */
   160  				return false
   161  			}
   162  
   163  			// We need extra check on redhat based distributions
   164  			if f, err := os.Open("/sys/module/user_namespace/parameters/enable"); err == nil {
   165  				b := make([]byte, 1)
   166  				_, _ = f.Read(b)
   167  				if string(b) == "N" {
   168  					return false
   169  				}
   170  				return true
   171  			}
   172  
   173  			return true
   174  		},
   175  		"Kernel must have user namespaces configured and enabled.",
   176  	}
   177  	NotUserNamespace = testRequirement{
   178  		func() bool {
   179  			root := os.Getenv("DOCKER_REMAP_ROOT")
   180  			if root != "" {
   181  				return false
   182  			}
   183  			return true
   184  		},
   185  		"Test cannot be run when remapping root",
   186  	}
   187  )
   188  
   189  // testRequires checks if the environment satisfies the requirements
   190  // for the test to run or skips the tests.
   191  func testRequires(c *check.C, requirements ...testRequirement) {
   192  	for _, r := range requirements {
   193  		if !r.Condition() {
   194  			c.Skip(r.SkipMessage)
   195  		}
   196  	}
   197  }