github.com/gondor/docker@v1.9.0-rc1/integration-cli/requirements.go (about)

     1  package main
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"log"
     8  	"net/http"
     9  	"os"
    10  	"os/exec"
    11  	"strings"
    12  	"time"
    13  
    14  	"github.com/go-check/check"
    15  )
    16  
    17  type testCondition func() bool
    18  
    19  type testRequirement struct {
    20  	Condition   testCondition
    21  	SkipMessage string
    22  }
    23  
    24  // List test requirements
    25  var (
    26  	daemonExecDriver string
    27  
    28  	DaemonIsWindows = testRequirement{
    29  		func() bool { return daemonPlatform == "windows" },
    30  		"Test requires a Windows daemon",
    31  	}
    32  	DaemonIsLinux = testRequirement{
    33  		func() bool { return daemonPlatform == "linux" },
    34  		"Test requires a Linux daemon",
    35  	}
    36  	SameHostDaemon = testRequirement{
    37  		func() bool { return isLocalDaemon },
    38  		"Test requires docker daemon to runs on the same machine as CLI",
    39  	}
    40  	UnixCli = testRequirement{
    41  		func() bool { return isUnixCli },
    42  		"Test requires posix utilities or functionality to run.",
    43  	}
    44  	ExecSupport = testRequirement{
    45  		func() bool { return supportsExec },
    46  		"Test requires 'docker exec' capabilities on the tested daemon.",
    47  	}
    48  	Network = testRequirement{
    49  		func() bool {
    50  			// Set a timeout on the GET at 15s
    51  			var timeout = time.Duration(15 * time.Second)
    52  			var url = "https://hub.docker.com"
    53  
    54  			client := http.Client{
    55  				Timeout: timeout,
    56  			}
    57  
    58  			resp, err := client.Get(url)
    59  			if err != nil && strings.Contains(err.Error(), "use of closed network connection") {
    60  				panic(fmt.Sprintf("Timeout for GET request on %s", url))
    61  			}
    62  			if resp != nil {
    63  				resp.Body.Close()
    64  			}
    65  			return err == nil
    66  		},
    67  		"Test requires network availability, environment variable set to none to run in a non-network enabled mode.",
    68  	}
    69  	Apparmor = testRequirement{
    70  		func() bool {
    71  			buf, err := ioutil.ReadFile("/sys/module/apparmor/parameters/enabled")
    72  			return err == nil && len(buf) > 1 && buf[0] == 'Y'
    73  		},
    74  		"Test requires apparmor is enabled.",
    75  	}
    76  	RegistryHosting = testRequirement{
    77  		func() bool {
    78  			// for now registry binary is built only if we're running inside
    79  			// container through `make test`. Figure that out by testing if
    80  			// registry binary is in PATH.
    81  			_, err := exec.LookPath(v2binary)
    82  			return err == nil
    83  		},
    84  		fmt.Sprintf("Test requires an environment that can host %s in the same host", v2binary),
    85  	}
    86  	NotaryHosting = testRequirement{
    87  		func() bool {
    88  			// for now notary binary is built only if we're running inside
    89  			// container through `make test`. Figure that out by testing if
    90  			// notary-server binary is in PATH.
    91  			_, err := exec.LookPath(notaryBinary)
    92  			return err == nil
    93  		},
    94  		fmt.Sprintf("Test requires an environment that can host %s in the same host", notaryBinary),
    95  	}
    96  	NativeExecDriver = testRequirement{
    97  		func() bool {
    98  			if daemonExecDriver == "" {
    99  				// get daemon info
   100  				status, body, err := sockRequest("GET", "/info", nil)
   101  				if err != nil || status != http.StatusOK {
   102  					log.Fatalf("sockRequest failed for /info: %v", err)
   103  				}
   104  
   105  				type infoJSON struct {
   106  					ExecutionDriver string
   107  				}
   108  				var info infoJSON
   109  				if err = json.Unmarshal(body, &info); err != nil {
   110  					log.Fatalf("unable to unmarshal body: %v", err)
   111  				}
   112  
   113  				daemonExecDriver = info.ExecutionDriver
   114  			}
   115  
   116  			return strings.HasPrefix(daemonExecDriver, "native")
   117  		},
   118  		"Test requires the native (libcontainer) exec driver.",
   119  	}
   120  	NotOverlay = testRequirement{
   121  		func() bool {
   122  			cmd := exec.Command("grep", "^overlay / overlay", "/proc/mounts")
   123  			if err := cmd.Run(); err != nil {
   124  				return true
   125  			}
   126  			return false
   127  		},
   128  		"Test requires underlying root filesystem not be backed by overlay.",
   129  	}
   130  	IPv6 = testRequirement{
   131  		func() bool {
   132  			cmd := exec.Command("test", "-f", "/proc/net/if_inet6")
   133  
   134  			if err := cmd.Run(); err != nil {
   135  				return true
   136  			}
   137  			return false
   138  		},
   139  		"Test requires support for IPv6",
   140  	}
   141  	NotGCCGO = testRequirement{
   142  		func() bool {
   143  			out, err := exec.Command("go", "version").Output()
   144  			if err != nil && strings.Contains(string(out), "gccgo") {
   145  				return true
   146  			}
   147  			return false
   148  		},
   149  		"Test requires native Golang compiler instead of GCCGO",
   150  	}
   151  	NotUserNamespace = testRequirement{
   152  		func() bool {
   153  			root := os.Getenv("DOCKER_REMAP_ROOT")
   154  			if root != "" {
   155  				return false
   156  			}
   157  			return true
   158  		},
   159  		"Test cannot be run when remapping root",
   160  	}
   161  )
   162  
   163  // testRequires checks if the environment satisfies the requirements
   164  // for the test to run or skips the tests.
   165  func testRequires(c *check.C, requirements ...testRequirement) {
   166  	for _, r := range requirements {
   167  		if !r.Condition() {
   168  			c.Skip(r.SkipMessage)
   169  		}
   170  	}
   171  }