Jelajahi Sumber

Merge pull request #29483 from vdemeester/extract-and-refactor-requirement

[test-integration] Refactor and extract TestRequire functionality
Vincent Demeester 8 tahun lalu
induk
melakukan
f847a3b7ce

+ 4 - 4
integration-cli/docker_api_containers_test.go

@@ -1665,7 +1665,7 @@ func (s *DockerSuite) TestContainersAPICreateMountsValidation(c *check.C) {
 		},
 		},
 	}
 	}
 
 
-	if SameHostDaemon.Condition() {
+	if SameHostDaemon() {
 		tmpDir, err := ioutils.TempDir("", "test-mounts-api")
 		tmpDir, err := ioutils.TempDir("", "test-mounts-api")
 		c.Assert(err, checker.IsNil)
 		c.Assert(err, checker.IsNil)
 		defer os.RemoveAll(tmpDir)
 		defer os.RemoveAll(tmpDir)
@@ -1696,7 +1696,7 @@ func (s *DockerSuite) TestContainersAPICreateMountsValidation(c *check.C) {
 		}...)
 		}...)
 	}
 	}
 
 
-	if DaemonIsLinux.Condition() {
+	if DaemonIsLinux() {
 		cases = append(cases, []testCase{
 		cases = append(cases, []testCase{
 			{
 			{
 				config: cfg{
 				config: cfg{
@@ -1823,7 +1823,7 @@ func (s *DockerSuite) TestContainersAPICreateMountsCreate(c *check.C) {
 		{mounttypes.Mount{Type: "volume", Target: destPath, Source: "test3", VolumeOptions: &mounttypes.VolumeOptions{DriverConfig: &mounttypes.Driver{Name: volume.DefaultDriverName}}}, types.MountPoint{Driver: volume.DefaultDriverName, Type: "volume", Name: "test3", RW: true, Destination: destPath}},
 		{mounttypes.Mount{Type: "volume", Target: destPath, Source: "test3", VolumeOptions: &mounttypes.VolumeOptions{DriverConfig: &mounttypes.Driver{Name: volume.DefaultDriverName}}}, types.MountPoint{Driver: volume.DefaultDriverName, Type: "volume", Name: "test3", RW: true, Destination: destPath}},
 	}
 	}
 
 
-	if SameHostDaemon.Condition() {
+	if SameHostDaemon() {
 		// setup temp dir for testing binds
 		// setup temp dir for testing binds
 		tmpDir1, err := ioutil.TempDir("", "test-mounts-api-1")
 		tmpDir1, err := ioutil.TempDir("", "test-mounts-api-1")
 		c.Assert(err, checker.IsNil)
 		c.Assert(err, checker.IsNil)
@@ -1834,7 +1834,7 @@ func (s *DockerSuite) TestContainersAPICreateMountsCreate(c *check.C) {
 		}...)
 		}...)
 
 
 		// for modes only supported on Linux
 		// for modes only supported on Linux
-		if DaemonIsLinux.Condition() {
+		if DaemonIsLinux() {
 			tmpDir3, err := ioutils.TempDir("", "test-mounts-api-3")
 			tmpDir3, err := ioutils.TempDir("", "test-mounts-api-3")
 			c.Assert(err, checker.IsNil)
 			c.Assert(err, checker.IsNil)
 			defer os.RemoveAll(tmpDir3)
 			defer os.RemoveAll(tmpDir3)

+ 1 - 1
integration-cli/docker_cli_cp_utils.go

@@ -289,7 +289,7 @@ func containerStartOutputEquals(c *check.C, containerID, contents string) (err e
 }
 }
 
 
 func defaultVolumes(tmpDir string) []string {
 func defaultVolumes(tmpDir string) []string {
-	if SameHostDaemon.Condition() {
+	if SameHostDaemon() {
 		return []string{
 		return []string{
 			"/vol1",
 			"/vol1",
 			fmt.Sprintf("%s:/vol2", tmpDir),
 			fmt.Sprintf("%s:/vol2", tmpDir),

+ 1 - 1
integration-cli/docker_cli_info_test.go

@@ -40,7 +40,7 @@ func (s *DockerSuite) TestInfoEnsureSucceeds(c *check.C) {
 		stringsToCheck = append(stringsToCheck, "Init Binary:", "Security Options:", "containerd version:", "runc version:", "init version:")
 		stringsToCheck = append(stringsToCheck, "Init Binary:", "Security Options:", "containerd version:", "runc version:", "init version:")
 	}
 	}
 
 
-	if DaemonIsLinux.Condition() {
+	if DaemonIsLinux() {
 		stringsToCheck = append(stringsToCheck, "Runtimes:", "Default Runtime: runc")
 		stringsToCheck = append(stringsToCheck, "Runtimes:", "Default Runtime: runc")
 	}
 	}
 
 

+ 1 - 1
integration-cli/docker_cli_ps_test.go

@@ -749,7 +749,7 @@ func (s *DockerSuite) TestPsShowMounts(c *check.C) {
 	// bind mount container
 	// bind mount container
 	var bindMountSource string
 	var bindMountSource string
 	var bindMountDestination string
 	var bindMountDestination string
-	if DaemonIsWindows.Condition() {
+	if DaemonIsWindows() {
 		bindMountSource = "c:\\"
 		bindMountSource = "c:\\"
 		bindMountDestination = "c:\\t"
 		bindMountDestination = "c:\\t"
 	} else {
 	} else {

+ 43 - 50
integration-cli/docker_experimental_network_test.go

@@ -13,44 +13,37 @@ import (
 	"github.com/go-check/check"
 	"github.com/go-check/check"
 )
 )
 
 
-var (
-	MacvlanKernelSupport = testRequirement{
-		func() bool {
-			const macvlanKernelVer = 3 // minimum macvlan kernel support
-			const macvlanMajorVer = 9  // minimum macvlan major kernel support
-			kv, err := kernel.GetKernelVersion()
-			if err != nil {
-				return false
-			}
-			// ensure Kernel version is >= v3.9 for macvlan support
-			if kv.Kernel < macvlanKernelVer || (kv.Kernel == macvlanKernelVer && kv.Major < macvlanMajorVer) {
-				return false
-			}
-			return true
-		},
-		"kernel version failed to meet the minimum macvlan kernel requirement of 3.9",
+func macvlanKernelSupport() bool {
+	const macvlanKernelVer = 3 // minimum macvlan kernel support
+	const macvlanMajorVer = 9  // minimum macvlan major kernel support
+	kv, err := kernel.GetKernelVersion()
+	if err != nil {
+		return false
 	}
 	}
-	IpvlanKernelSupport = testRequirement{
-		func() bool {
-			const ipvlanKernelVer = 4 // minimum ipvlan kernel support
-			const ipvlanMajorVer = 2  // minimum ipvlan major kernel support
-			kv, err := kernel.GetKernelVersion()
-			if err != nil {
-				return false
-			}
-			// ensure Kernel version is >= v4.2 for ipvlan support
-			if kv.Kernel < ipvlanKernelVer || (kv.Kernel == ipvlanKernelVer && kv.Major < ipvlanMajorVer) {
-				return false
-			}
-			return true
-		},
-		"kernel version failed to meet the minimum ipvlan kernel requirement of 4.0.0",
+	// ensure Kernel version is >= v3.9 for macvlan support
+	if kv.Kernel < macvlanKernelVer || (kv.Kernel == macvlanKernelVer && kv.Major < macvlanMajorVer) {
+		return false
 	}
 	}
-)
+	return true
+}
+
+func ipvlanKernelSupport() bool {
+	const ipvlanKernelVer = 4 // minimum ipvlan kernel support
+	const ipvlanMajorVer = 2  // minimum ipvlan major kernel support
+	kv, err := kernel.GetKernelVersion()
+	if err != nil {
+		return false
+	}
+	// ensure Kernel version is >= v4.2 for ipvlan support
+	if kv.Kernel < ipvlanKernelVer || (kv.Kernel == ipvlanKernelVer && kv.Major < ipvlanMajorVer) {
+		return false
+	}
+	return true
+}
 
 
 func (s *DockerNetworkSuite) TestDockerNetworkMacvlanPersistance(c *check.C) {
 func (s *DockerNetworkSuite) TestDockerNetworkMacvlanPersistance(c *check.C) {
 	// verify the driver automatically provisions the 802.1q link (dm-dummy0.60)
 	// verify the driver automatically provisions the 802.1q link (dm-dummy0.60)
-	testRequires(c, DaemonIsLinux, MacvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
+	testRequires(c, DaemonIsLinux, macvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
 
 
 	// master dummy interface 'dm' abbreviation represents 'docker macvlan'
 	// master dummy interface 'dm' abbreviation represents 'docker macvlan'
 	master := "dm-dummy0"
 	master := "dm-dummy0"
@@ -70,7 +63,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkMacvlanPersistance(c *check.C) {
 
 
 func (s *DockerNetworkSuite) TestDockerNetworkIpvlanPersistance(c *check.C) {
 func (s *DockerNetworkSuite) TestDockerNetworkIpvlanPersistance(c *check.C) {
 	// verify the driver automatically provisions the 802.1q link (di-dummy0.70)
 	// verify the driver automatically provisions the 802.1q link (di-dummy0.70)
-	testRequires(c, DaemonIsLinux, IpvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
+	testRequires(c, DaemonIsLinux, ipvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
 	// master dummy interface 'di' notation represent 'docker ipvlan'
 	// master dummy interface 'di' notation represent 'docker ipvlan'
 	master := "di-dummy0"
 	master := "di-dummy0"
 	// simulate the master link the vlan tagged subinterface parent link will use
 	// simulate the master link the vlan tagged subinterface parent link will use
@@ -89,7 +82,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkIpvlanPersistance(c *check.C) {
 
 
 func (s *DockerNetworkSuite) TestDockerNetworkMacvlanSubIntCreate(c *check.C) {
 func (s *DockerNetworkSuite) TestDockerNetworkMacvlanSubIntCreate(c *check.C) {
 	// verify the driver automatically provisions the 802.1q link (dm-dummy0.50)
 	// verify the driver automatically provisions the 802.1q link (dm-dummy0.50)
-	testRequires(c, DaemonIsLinux, MacvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
+	testRequires(c, DaemonIsLinux, macvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
 	// master dummy interface 'dm' abbreviation represents 'docker macvlan'
 	// master dummy interface 'dm' abbreviation represents 'docker macvlan'
 	master := "dm-dummy0"
 	master := "dm-dummy0"
 	// simulate the master link the vlan tagged subinterface parent link will use
 	// simulate the master link the vlan tagged subinterface parent link will use
@@ -104,7 +97,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkMacvlanSubIntCreate(c *check.C) {
 
 
 func (s *DockerNetworkSuite) TestDockerNetworkIpvlanSubIntCreate(c *check.C) {
 func (s *DockerNetworkSuite) TestDockerNetworkIpvlanSubIntCreate(c *check.C) {
 	// verify the driver automatically provisions the 802.1q link (di-dummy0.50)
 	// verify the driver automatically provisions the 802.1q link (di-dummy0.50)
-	testRequires(c, DaemonIsLinux, IpvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
+	testRequires(c, DaemonIsLinux, ipvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
 	// master dummy interface 'dm' abbreviation represents 'docker ipvlan'
 	// master dummy interface 'dm' abbreviation represents 'docker ipvlan'
 	master := "di-dummy0"
 	master := "di-dummy0"
 	// simulate the master link the vlan tagged subinterface parent link will use
 	// simulate the master link the vlan tagged subinterface parent link will use
@@ -119,7 +112,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkIpvlanSubIntCreate(c *check.C) {
 
 
 func (s *DockerNetworkSuite) TestDockerNetworkMacvlanOverlapParent(c *check.C) {
 func (s *DockerNetworkSuite) TestDockerNetworkMacvlanOverlapParent(c *check.C) {
 	// verify the same parent interface cannot be used if already in use by an existing network
 	// verify the same parent interface cannot be used if already in use by an existing network
-	testRequires(c, DaemonIsLinux, MacvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
+	testRequires(c, DaemonIsLinux, macvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
 	// master dummy interface 'dm' abbreviation represents 'docker macvlan'
 	// master dummy interface 'dm' abbreviation represents 'docker macvlan'
 	master := "dm-dummy0"
 	master := "dm-dummy0"
 	out, err := createMasterDummy(c, master)
 	out, err := createMasterDummy(c, master)
@@ -139,7 +132,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkMacvlanOverlapParent(c *check.C) {
 
 
 func (s *DockerNetworkSuite) TestDockerNetworkIpvlanOverlapParent(c *check.C) {
 func (s *DockerNetworkSuite) TestDockerNetworkIpvlanOverlapParent(c *check.C) {
 	// verify the same parent interface cannot be used if already in use by an existing network
 	// verify the same parent interface cannot be used if already in use by an existing network
-	testRequires(c, DaemonIsLinux, IpvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
+	testRequires(c, DaemonIsLinux, ipvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
 	// master dummy interface 'dm' abbreviation represents 'docker ipvlan'
 	// master dummy interface 'dm' abbreviation represents 'docker ipvlan'
 	master := "di-dummy0"
 	master := "di-dummy0"
 	out, err := createMasterDummy(c, master)
 	out, err := createMasterDummy(c, master)
@@ -159,7 +152,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkIpvlanOverlapParent(c *check.C) {
 
 
 func (s *DockerNetworkSuite) TestDockerNetworkMacvlanMultiSubnet(c *check.C) {
 func (s *DockerNetworkSuite) TestDockerNetworkMacvlanMultiSubnet(c *check.C) {
 	// create a dual stack multi-subnet Macvlan bridge mode network and validate connectivity between four containers, two on each subnet
 	// create a dual stack multi-subnet Macvlan bridge mode network and validate connectivity between four containers, two on each subnet
-	testRequires(c, DaemonIsLinux, IPv6, MacvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
+	testRequires(c, DaemonIsLinux, IPv6, macvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
 	dockerCmd(c, "network", "create", "--driver=macvlan", "--ipv6", "--subnet=172.28.100.0/24", "--subnet=172.28.102.0/24", "--gateway=172.28.102.254",
 	dockerCmd(c, "network", "create", "--driver=macvlan", "--ipv6", "--subnet=172.28.100.0/24", "--subnet=172.28.102.0/24", "--gateway=172.28.102.254",
 		"--subnet=2001:db8:abc2::/64", "--subnet=2001:db8:abc4::/64", "--gateway=2001:db8:abc4::254", "dualstackbridge")
 		"--subnet=2001:db8:abc2::/64", "--subnet=2001:db8:abc4::/64", "--gateway=2001:db8:abc4::254", "dualstackbridge")
 	// Ensure the network was created
 	// Ensure the network was created
@@ -214,7 +207,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkMacvlanMultiSubnet(c *check.C) {
 
 
 func (s *DockerNetworkSuite) TestDockerNetworkIpvlanL2MultiSubnet(c *check.C) {
 func (s *DockerNetworkSuite) TestDockerNetworkIpvlanL2MultiSubnet(c *check.C) {
 	// create a dual stack multi-subnet Ipvlan L2 network and validate connectivity within the subnets, two on each subnet
 	// create a dual stack multi-subnet Ipvlan L2 network and validate connectivity within the subnets, two on each subnet
-	testRequires(c, DaemonIsLinux, IPv6, IpvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
+	testRequires(c, DaemonIsLinux, IPv6, ipvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
 	dockerCmd(c, "network", "create", "--driver=ipvlan", "--ipv6", "--subnet=172.28.200.0/24", "--subnet=172.28.202.0/24", "--gateway=172.28.202.254",
 	dockerCmd(c, "network", "create", "--driver=ipvlan", "--ipv6", "--subnet=172.28.200.0/24", "--subnet=172.28.202.0/24", "--gateway=172.28.202.254",
 		"--subnet=2001:db8:abc8::/64", "--subnet=2001:db8:abc6::/64", "--gateway=2001:db8:abc6::254", "dualstackl2")
 		"--subnet=2001:db8:abc8::/64", "--subnet=2001:db8:abc6::/64", "--gateway=2001:db8:abc6::254", "dualstackl2")
 	// Ensure the network was created
 	// Ensure the network was created
@@ -268,7 +261,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkIpvlanL2MultiSubnet(c *check.C) {
 
 
 func (s *DockerNetworkSuite) TestDockerNetworkIpvlanL3MultiSubnet(c *check.C) {
 func (s *DockerNetworkSuite) TestDockerNetworkIpvlanL3MultiSubnet(c *check.C) {
 	// create a dual stack multi-subnet Ipvlan L3 network and validate connectivity between all four containers per L3 mode
 	// create a dual stack multi-subnet Ipvlan L3 network and validate connectivity between all four containers per L3 mode
-	testRequires(c, DaemonIsLinux, IPv6, IpvlanKernelSupport, NotUserNamespace, NotArm, IPv6, ExperimentalDaemon)
+	testRequires(c, DaemonIsLinux, IPv6, ipvlanKernelSupport, NotUserNamespace, NotArm, IPv6, ExperimentalDaemon)
 	dockerCmd(c, "network", "create", "--driver=ipvlan", "--ipv6", "--subnet=172.28.10.0/24", "--subnet=172.28.12.0/24", "--gateway=172.28.12.254",
 	dockerCmd(c, "network", "create", "--driver=ipvlan", "--ipv6", "--subnet=172.28.10.0/24", "--subnet=172.28.12.0/24", "--gateway=172.28.12.254",
 		"--subnet=2001:db8:abc9::/64", "--subnet=2001:db8:abc7::/64", "--gateway=2001:db8:abc7::254", "-o", "ipvlan_mode=l3", "dualstackl3")
 		"--subnet=2001:db8:abc9::/64", "--subnet=2001:db8:abc7::/64", "--gateway=2001:db8:abc7::254", "-o", "ipvlan_mode=l3", "dualstackl3")
 	// Ensure the network was created
 	// Ensure the network was created
@@ -327,7 +320,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkIpvlanL3MultiSubnet(c *check.C) {
 
 
 func (s *DockerNetworkSuite) TestDockerNetworkIpvlanAddressing(c *check.C) {
 func (s *DockerNetworkSuite) TestDockerNetworkIpvlanAddressing(c *check.C) {
 	// Ensure the default gateways, next-hops and default dev devices are properly set
 	// Ensure the default gateways, next-hops and default dev devices are properly set
-	testRequires(c, DaemonIsLinux, IPv6, IpvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
+	testRequires(c, DaemonIsLinux, IPv6, ipvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
 	dockerCmd(c, "network", "create", "--driver=macvlan", "--ipv6", "--subnet=172.28.130.0/24",
 	dockerCmd(c, "network", "create", "--driver=macvlan", "--ipv6", "--subnet=172.28.130.0/24",
 		"--subnet=2001:db8:abca::/64", "--gateway=2001:db8:abca::254", "-o", "macvlan_mode=bridge", "dualstackbridge")
 		"--subnet=2001:db8:abca::/64", "--gateway=2001:db8:abca::254", "-o", "macvlan_mode=bridge", "dualstackbridge")
 	assertNwIsAvailable(c, "dualstackbridge")
 	assertNwIsAvailable(c, "dualstackbridge")
@@ -373,7 +366,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkIpvlanAddressing(c *check.C) {
 
 
 func (s *DockerSuite) TestDockerNetworkMacVlanBridgeNilParent(c *check.C) {
 func (s *DockerSuite) TestDockerNetworkMacVlanBridgeNilParent(c *check.C) {
 	// macvlan bridge mode - dummy parent interface is provisioned dynamically
 	// macvlan bridge mode - dummy parent interface is provisioned dynamically
-	testRequires(c, DaemonIsLinux, MacvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
+	testRequires(c, DaemonIsLinux, macvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
 	dockerCmd(c, "network", "create", "--driver=macvlan", "dm-nil-parent")
 	dockerCmd(c, "network", "create", "--driver=macvlan", "dm-nil-parent")
 	assertNwIsAvailable(c, "dm-nil-parent")
 	assertNwIsAvailable(c, "dm-nil-parent")
 
 
@@ -390,7 +383,7 @@ func (s *DockerSuite) TestDockerNetworkMacVlanBridgeNilParent(c *check.C) {
 
 
 func (s *DockerSuite) TestDockerNetworkMacVlanBridgeInternalMode(c *check.C) {
 func (s *DockerSuite) TestDockerNetworkMacVlanBridgeInternalMode(c *check.C) {
 	// macvlan bridge mode --internal containers can communicate inside the network but not externally
 	// macvlan bridge mode --internal containers can communicate inside the network but not externally
-	testRequires(c, DaemonIsLinux, MacvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
+	testRequires(c, DaemonIsLinux, macvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
 	dockerCmd(c, "network", "create", "--driver=macvlan", "--internal", "dm-internal")
 	dockerCmd(c, "network", "create", "--driver=macvlan", "--internal", "dm-internal")
 	assertNwIsAvailable(c, "dm-internal")
 	assertNwIsAvailable(c, "dm-internal")
 	nr := getNetworkResource(c, "dm-internal")
 	nr := getNetworkResource(c, "dm-internal")
@@ -413,7 +406,7 @@ func (s *DockerSuite) TestDockerNetworkMacVlanBridgeInternalMode(c *check.C) {
 
 
 func (s *DockerSuite) TestDockerNetworkIpvlanL2NilParent(c *check.C) {
 func (s *DockerSuite) TestDockerNetworkIpvlanL2NilParent(c *check.C) {
 	// ipvlan l2 mode - dummy parent interface is provisioned dynamically
 	// ipvlan l2 mode - dummy parent interface is provisioned dynamically
-	testRequires(c, DaemonIsLinux, IpvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
+	testRequires(c, DaemonIsLinux, ipvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
 	dockerCmd(c, "network", "create", "--driver=ipvlan", "di-nil-parent")
 	dockerCmd(c, "network", "create", "--driver=ipvlan", "di-nil-parent")
 	assertNwIsAvailable(c, "di-nil-parent")
 	assertNwIsAvailable(c, "di-nil-parent")
 
 
@@ -430,7 +423,7 @@ func (s *DockerSuite) TestDockerNetworkIpvlanL2NilParent(c *check.C) {
 
 
 func (s *DockerSuite) TestDockerNetworkIpvlanL2InternalMode(c *check.C) {
 func (s *DockerSuite) TestDockerNetworkIpvlanL2InternalMode(c *check.C) {
 	// ipvlan l2 mode --internal containers can communicate inside the network but not externally
 	// ipvlan l2 mode --internal containers can communicate inside the network but not externally
-	testRequires(c, DaemonIsLinux, IpvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
+	testRequires(c, DaemonIsLinux, ipvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
 	dockerCmd(c, "network", "create", "--driver=ipvlan", "--internal", "di-internal")
 	dockerCmd(c, "network", "create", "--driver=ipvlan", "--internal", "di-internal")
 	assertNwIsAvailable(c, "di-internal")
 	assertNwIsAvailable(c, "di-internal")
 	nr := getNetworkResource(c, "di-internal")
 	nr := getNetworkResource(c, "di-internal")
@@ -452,7 +445,7 @@ func (s *DockerSuite) TestDockerNetworkIpvlanL2InternalMode(c *check.C) {
 
 
 func (s *DockerSuite) TestDockerNetworkIpvlanL3NilParent(c *check.C) {
 func (s *DockerSuite) TestDockerNetworkIpvlanL3NilParent(c *check.C) {
 	// ipvlan l3 mode - dummy parent interface is provisioned dynamically
 	// ipvlan l3 mode - dummy parent interface is provisioned dynamically
-	testRequires(c, DaemonIsLinux, IpvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
+	testRequires(c, DaemonIsLinux, ipvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
 	dockerCmd(c, "network", "create", "--driver=ipvlan", "--subnet=172.28.230.0/24",
 	dockerCmd(c, "network", "create", "--driver=ipvlan", "--subnet=172.28.230.0/24",
 		"--subnet=172.28.220.0/24", "-o", "ipvlan_mode=l3", "di-nil-parent-l3")
 		"--subnet=172.28.220.0/24", "-o", "ipvlan_mode=l3", "di-nil-parent-l3")
 	assertNwIsAvailable(c, "di-nil-parent-l3")
 	assertNwIsAvailable(c, "di-nil-parent-l3")
@@ -470,7 +463,7 @@ func (s *DockerSuite) TestDockerNetworkIpvlanL3NilParent(c *check.C) {
 
 
 func (s *DockerSuite) TestDockerNetworkIpvlanL3InternalMode(c *check.C) {
 func (s *DockerSuite) TestDockerNetworkIpvlanL3InternalMode(c *check.C) {
 	// ipvlan l3 mode --internal containers can communicate inside the network but not externally
 	// ipvlan l3 mode --internal containers can communicate inside the network but not externally
-	testRequires(c, DaemonIsLinux, IpvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
+	testRequires(c, DaemonIsLinux, ipvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
 	dockerCmd(c, "network", "create", "--driver=ipvlan", "--subnet=172.28.230.0/24",
 	dockerCmd(c, "network", "create", "--driver=ipvlan", "--subnet=172.28.230.0/24",
 		"--subnet=172.28.220.0/24", "-o", "ipvlan_mode=l3", "--internal", "di-internal-l3")
 		"--subnet=172.28.220.0/24", "-o", "ipvlan_mode=l3", "--internal", "di-internal-l3")
 	assertNwIsAvailable(c, "di-internal-l3")
 	assertNwIsAvailable(c, "di-internal-l3")
@@ -493,7 +486,7 @@ func (s *DockerSuite) TestDockerNetworkIpvlanL3InternalMode(c *check.C) {
 
 
 func (s *DockerSuite) TestDockerNetworkMacVlanExistingParent(c *check.C) {
 func (s *DockerSuite) TestDockerNetworkMacVlanExistingParent(c *check.C) {
 	// macvlan bridge mode - empty parent interface containers can reach each other internally but not externally
 	// macvlan bridge mode - empty parent interface containers can reach each other internally but not externally
-	testRequires(c, DaemonIsLinux, MacvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
+	testRequires(c, DaemonIsLinux, macvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
 	netName := "dm-parent-exists"
 	netName := "dm-parent-exists"
 	out, err := createMasterDummy(c, "dm-dummy0")
 	out, err := createMasterDummy(c, "dm-dummy0")
 	//out, err := createVlanInterface(c, "dm-parent", "dm-slave", "macvlan", "bridge")
 	//out, err := createVlanInterface(c, "dm-parent", "dm-slave", "macvlan", "bridge")
@@ -513,7 +506,7 @@ func (s *DockerSuite) TestDockerNetworkMacVlanExistingParent(c *check.C) {
 
 
 func (s *DockerSuite) TestDockerNetworkMacVlanSubinterface(c *check.C) {
 func (s *DockerSuite) TestDockerNetworkMacVlanSubinterface(c *check.C) {
 	// macvlan bridge mode -  empty parent interface containers can reach each other internally but not externally
 	// macvlan bridge mode -  empty parent interface containers can reach each other internally but not externally
-	testRequires(c, DaemonIsLinux, MacvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
+	testRequires(c, DaemonIsLinux, macvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
 	netName := "dm-subinterface"
 	netName := "dm-subinterface"
 	out, err := createMasterDummy(c, "dm-dummy0")
 	out, err := createMasterDummy(c, "dm-dummy0")
 	c.Assert(err, check.IsNil, check.Commentf(out))
 	c.Assert(err, check.IsNil, check.Commentf(out))

+ 26 - 0
integration-cli/requirement/requirement.go

@@ -0,0 +1,26 @@
+package requirement
+
+import (
+	"fmt"
+	"reflect"
+	"runtime"
+)
+
+type skipT interface {
+	Skip(reason string)
+}
+
+// Test represent a function that can be used as a requirement validation.
+type Test func() bool
+
+// Is checks if the environment satisfies the requirements
+// for the test to run or skips the tests.
+func Is(s skipT, requirements ...Test) {
+	for _, r := range requirements {
+		isValid := r()
+		if !isValid {
+			requirementFunc := runtime.FuncForPC(reflect.ValueOf(r).Pointer()).Name()
+			s.Skip(fmt.Sprintf("unmatched requirement %s", requirementFunc))
+		}
+	}
+}

+ 0 - 237
integration-cli/requirements.go

@@ -1,237 +0,0 @@
-package main
-
-import (
-	"fmt"
-	"io/ioutil"
-	"net/http"
-	"os"
-	"os/exec"
-	"strings"
-	"time"
-
-	"github.com/go-check/check"
-)
-
-type testCondition func() bool
-
-type testRequirement struct {
-	Condition   testCondition
-	SkipMessage string
-}
-
-// List test requirements
-var (
-	DaemonIsWindows = testRequirement{
-		func() bool { return daemonPlatform == "windows" },
-		"Test requires a Windows daemon",
-	}
-	DaemonIsLinux = testRequirement{
-		func() bool { return daemonPlatform == "linux" },
-		"Test requires a Linux daemon",
-	}
-	ExperimentalDaemon = testRequirement{
-		func() bool { return experimentalDaemon },
-		"Test requires an experimental daemon",
-	}
-	NotExperimentalDaemon = testRequirement{
-		func() bool { return !experimentalDaemon },
-		"Test requires a non experimental daemon",
-	}
-	IsAmd64 = testRequirement{
-		func() bool { return os.Getenv("DOCKER_ENGINE_GOARCH") == "amd64" },
-		"Test requires a daemon running on amd64",
-	}
-	NotArm = testRequirement{
-		func() bool { return os.Getenv("DOCKER_ENGINE_GOARCH") != "arm" },
-		"Test requires a daemon not running on ARM",
-	}
-	NotArm64 = testRequirement{
-		func() bool { return os.Getenv("DOCKER_ENGINE_GOARCH") != "arm64" },
-		"Test requires a daemon not running on arm64",
-	}
-	NotPpc64le = testRequirement{
-		func() bool { return os.Getenv("DOCKER_ENGINE_GOARCH") != "ppc64le" },
-		"Test requires a daemon not running on ppc64le",
-	}
-	NotS390X = testRequirement{
-		func() bool { return os.Getenv("DOCKER_ENGINE_GOARCH") != "s390x" },
-		"Test requires a daemon not running on s390x",
-	}
-	SameHostDaemon = testRequirement{
-		func() bool { return isLocalDaemon },
-		"Test requires docker daemon to run on the same machine as CLI",
-	}
-	UnixCli = testRequirement{
-		func() bool { return isUnixCli },
-		"Test requires posix utilities or functionality to run.",
-	}
-	ExecSupport = testRequirement{
-		func() bool { return supportsExec },
-		"Test requires 'docker exec' capabilities on the tested daemon.",
-	}
-	Network = testRequirement{
-		func() bool {
-			// 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))
-			}
-			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.",
-	}
-	Apparmor = testRequirement{
-		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.",
-	}
-	RegistryHosting = testRequirement{
-		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),
-	}
-	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(notaryServerBinary)
-			return err == nil
-		},
-		fmt.Sprintf("Test requires an environment that can host %s in the same host", notaryServerBinary),
-	}
-	NotaryServerHosting = testRequirement{
-		func() bool {
-			// for now notary-server 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(notaryServerBinary)
-			return err == nil
-		},
-		fmt.Sprintf("Test requires an environment that can host %s in the same host", notaryServerBinary),
-	}
-	NotOverlay = testRequirement{
-		func() bool {
-			return !strings.HasPrefix(daemonStorageDriver, "overlay")
-		},
-		"Test requires underlying root filesystem not be backed by overlay.",
-	}
-
-	Devicemapper = testRequirement{
-		func() bool {
-			return strings.HasPrefix(daemonStorageDriver, "devicemapper")
-		},
-		"Test requires underlying root filesystem to be backed by devicemapper.",
-	}
-
-	IPv6 = testRequirement{
-		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",
-	}
-	UserNamespaceROMount = testRequirement{
-		func() bool {
-			// quick case--userns not enabled in this test run
-			if os.Getenv("DOCKER_REMAP_ROOT") == "" {
-				return true
-			}
-			if _, _, err := dockerCmdWithError("run", "--rm", "--read-only", "busybox", "date"); err != nil {
-				return false
-			}
-			return true
-		},
-		"Test cannot be run if user namespaces enabled but readonly mounts fail on this kernel.",
-	}
-	UserNamespaceInKernel = testRequirement{
-		func() bool {
-			if _, err := os.Stat("/proc/self/uid_map"); os.IsNotExist(err) {
-				/*
-				 * This kernel-provided file only exists if user namespaces are
-				 * supported
-				 */
-				return false
-			}
-
-			// We need extra check on redhat based distributions
-			if f, err := os.Open("/sys/module/user_namespace/parameters/enable"); err == nil {
-				defer f.Close()
-				b := make([]byte, 1)
-				_, _ = f.Read(b)
-				return string(b) != "N"
-			}
-
-			return true
-		},
-		"Kernel must have user namespaces configured and enabled.",
-	}
-	NotUserNamespace = testRequirement{
-		func() bool {
-			root := os.Getenv("DOCKER_REMAP_ROOT")
-			return root == ""
-		},
-		"Test cannot be run when remapping root",
-	}
-	IsPausable = testRequirement{
-		func() bool {
-			if daemonPlatform == "windows" {
-				return isolation == "hyperv"
-			}
-			return true
-		},
-		"Test requires containers are pausable.",
-	}
-	NotPausable = testRequirement{
-		func() bool {
-			if daemonPlatform == "windows" {
-				return isolation == "process"
-			}
-			return false
-		},
-		"Test requires containers are not pausable.",
-	}
-	IsolationIsHyperv = testRequirement{
-		func() bool {
-			return daemonPlatform == "windows" && isolation == "hyperv"
-		},
-		"Test requires a Windows daemon running default isolation mode of hyperv.",
-	}
-	IsolationIsProcess = testRequirement{
-		func() bool {
-			return daemonPlatform == "windows" && isolation == "process"
-		},
-		"Test requires a Windows daemon running default isolation mode of process.",
-	}
-)
-
-// testRequires checks if the environment satisfies the requirements
-// for the test to run or skips the tests.
-func testRequires(c *check.C, requirements ...testRequirement) {
-	for _, r := range requirements {
-		if !r.Condition() {
-			c.Skip(r.SkipMessage)
-		}
-	}
-}

+ 211 - 0
integration-cli/requirements_test.go

@@ -0,0 +1,211 @@
+package main
+
+import (
+	"fmt"
+	"io/ioutil"
+	"net/http"
+	"os"
+	"os/exec"
+	"strings"
+	"time"
+
+	"github.com/docker/docker/integration-cli/requirement"
+	"github.com/go-check/check"
+)
+
+func PlatformIs(platform string) bool {
+	return daemonPlatform == platform
+}
+
+func ArchitectureIs(arch string) bool {
+	return os.Getenv("DOCKER_ENGINE_GOARCH") == arch
+}
+
+func ArchitectureIsNot(arch string) bool {
+	return os.Getenv("DOCKER_ENGINE_GOARCH") != arch
+}
+
+func StorageDriverIs(storageDriver string) bool {
+	return strings.HasPrefix(daemonStorageDriver, storageDriver)
+}
+
+func StorageDriverIsNot(storageDriver string) bool {
+	return !strings.HasPrefix(daemonStorageDriver, storageDriver)
+}
+
+func DaemonIsWindows() bool {
+	return PlatformIs("windows")
+}
+
+func DaemonIsLinux() bool {
+	return PlatformIs("linux")
+}
+
+func ExperimentalDaemon() bool {
+	return experimentalDaemon
+}
+
+func NotExperimentalDaemon() bool {
+	return !experimentalDaemon
+}
+
+func IsAmd64() bool {
+	return ArchitectureIs("amd64")
+}
+
+func NotArm() bool {
+	return ArchitectureIsNot("arm")
+}
+
+func NotArm64() bool {
+	return ArchitectureIsNot("arm64")
+}
+
+func NotPpc64le() bool {
+	return ArchitectureIsNot("ppc64le")
+}
+
+func NotS390X() bool {
+	return ArchitectureIsNot("s390x")
+}
+
+func SameHostDaemon() bool {
+	return isLocalDaemon
+}
+
+func UnixCli() bool {
+	return isUnixCli
+}
+
+func ExecSupport() bool {
+	return supportsExec
+}
+
+func Network() bool {
+	// 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))
+	}
+	if resp != nil {
+		resp.Body.Close()
+	}
+	return err == nil
+}
+
+func Apparmor() bool {
+	buf, err := ioutil.ReadFile("/sys/module/apparmor/parameters/enabled")
+	return err == nil && len(buf) > 1 && buf[0] == 'Y'
+}
+
+func RegistryHosting() 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
+}
+
+func NotaryHosting() 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(notaryServerBinary)
+	return err == nil
+}
+
+func NotaryServerHosting() bool {
+	// for now notary-server 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(notaryServerBinary)
+	return err == nil
+}
+
+func NotOverlay() bool {
+	return StorageDriverIsNot("overlay")
+}
+
+func Devicemapper() bool {
+	return StorageDriverIs("devicemapper")
+}
+
+func IPv6() bool {
+	cmd := exec.Command("test", "-f", "/proc/net/if_inet6")
+	return cmd.Run() != nil
+}
+
+func UserNamespaceROMount() bool {
+	// quick case--userns not enabled in this test run
+	if os.Getenv("DOCKER_REMAP_ROOT") == "" {
+		return true
+	}
+	if _, _, err := dockerCmdWithError("run", "--rm", "--read-only", "busybox", "date"); err != nil {
+		return false
+	}
+	return true
+}
+
+func NotUserNamespace() bool {
+	root := os.Getenv("DOCKER_REMAP_ROOT")
+	return root == ""
+}
+
+func UserNamespaceInKernel() bool {
+	if _, err := os.Stat("/proc/self/uid_map"); os.IsNotExist(err) {
+		/*
+		 * This kernel-provided file only exists if user namespaces are
+		 * supported
+		 */
+		return false
+	}
+
+	// We need extra check on redhat based distributions
+	if f, err := os.Open("/sys/module/user_namespace/parameters/enable"); err == nil {
+		defer f.Close()
+		b := make([]byte, 1)
+		_, _ = f.Read(b)
+		return string(b) != "N"
+	}
+
+	return true
+}
+
+func IsPausable() bool {
+	if daemonPlatform == "windows" {
+		return isolation == "hyperv"
+	}
+	return true
+}
+
+func NotPausable() bool {
+	if daemonPlatform == "windows" {
+		return isolation == "process"
+	}
+	return false
+}
+
+func IsolationIs(expectedIsolation string) bool {
+	return daemonPlatform == "windows" && string(isolation) == expectedIsolation
+}
+
+func IsolationIsHyperv() bool {
+	return IsolationIs("hyperv")
+}
+
+func IsolationIsProcess() bool {
+	return IsolationIs("process")
+}
+
+// testRequires checks if the environment satisfies the requirements
+// for the test to run or skips the tests.
+func testRequires(c *check.C, requirements ...requirement.Test) {
+	requirement.Is(c, requirements...)
+}

+ 0 - 159
integration-cli/requirements_unix.go

@@ -1,159 +0,0 @@
-// +build !windows
-
-package main
-
-import (
-	"bytes"
-	"io/ioutil"
-	"os/exec"
-	"strings"
-
-	"github.com/docker/docker/pkg/parsers/kernel"
-	"github.com/docker/docker/pkg/sysinfo"
-)
-
-var (
-	// SysInfo stores information about which features a kernel supports.
-	SysInfo      *sysinfo.SysInfo
-	cpuCfsPeriod = testRequirement{
-		func() bool {
-			return SysInfo.CPUCfsPeriod
-		},
-		"Test requires an environment that supports cgroup cfs period.",
-	}
-	cpuCfsQuota = testRequirement{
-		func() bool {
-			return SysInfo.CPUCfsQuota
-		},
-		"Test requires an environment that supports cgroup cfs quota.",
-	}
-	cpuShare = testRequirement{
-		func() bool {
-			return SysInfo.CPUShares
-		},
-		"Test requires an environment that supports cgroup cpu shares.",
-	}
-	oomControl = testRequirement{
-		func() bool {
-			return SysInfo.OomKillDisable
-		},
-		"Test requires Oom control enabled.",
-	}
-	pidsLimit = testRequirement{
-		func() bool {
-			return SysInfo.PidsLimit
-		},
-		"Test requires pids limit enabled.",
-	}
-	kernelMemorySupport = testRequirement{
-		func() bool {
-			return SysInfo.KernelMemory
-		},
-		"Test requires an environment that supports cgroup kernel memory.",
-	}
-	memoryLimitSupport = testRequirement{
-		func() bool {
-			return SysInfo.MemoryLimit
-		},
-		"Test requires an environment that supports cgroup memory limit.",
-	}
-	memoryReservationSupport = testRequirement{
-		func() bool {
-			return SysInfo.MemoryReservation
-		},
-		"Test requires an environment that supports cgroup memory reservation.",
-	}
-	swapMemorySupport = testRequirement{
-		func() bool {
-			return SysInfo.SwapLimit
-		},
-		"Test requires an environment that supports cgroup swap memory limit.",
-	}
-	memorySwappinessSupport = testRequirement{
-		func() bool {
-			return SysInfo.MemorySwappiness
-		},
-		"Test requires an environment that supports cgroup memory swappiness.",
-	}
-	blkioWeight = testRequirement{
-		func() bool {
-			return SysInfo.BlkioWeight
-		},
-		"Test requires an environment that supports blkio weight.",
-	}
-	cgroupCpuset = testRequirement{
-		func() bool {
-			return SysInfo.Cpuset
-		},
-		"Test requires an environment that supports cgroup cpuset.",
-	}
-	seccompEnabled = testRequirement{
-		func() bool {
-			return supportsSeccomp && SysInfo.Seccomp
-		},
-		"Test requires that seccomp support be enabled in the daemon.",
-	}
-	bridgeNfIptables = testRequirement{
-		func() bool {
-			return !SysInfo.BridgeNFCallIPTablesDisabled
-		},
-		"Test requires that bridge-nf-call-iptables support be enabled in the daemon.",
-	}
-	bridgeNfIP6tables = testRequirement{
-		func() bool {
-			return !SysInfo.BridgeNFCallIP6TablesDisabled
-		},
-		"Test requires that bridge-nf-call-ip6tables support be enabled in the daemon.",
-	}
-	unprivilegedUsernsClone = testRequirement{
-		func() bool {
-			content, err := ioutil.ReadFile("/proc/sys/kernel/unprivileged_userns_clone")
-			if err == nil && strings.Contains(string(content), "0") {
-				return false
-			}
-			return true
-		},
-		"Test cannot be run with 'sysctl kernel.unprivileged_userns_clone' = 0",
-	}
-	ambientCapabilities = testRequirement{
-		func() bool {
-			content, err := ioutil.ReadFile("/proc/self/status")
-			if err == nil && strings.Contains(string(content), "CapAmb:") {
-				return true
-			}
-			return false
-		},
-		"Test cannot be run without a kernel (4.3+) supporting ambient capabilities",
-	}
-	overlayFSSupported = testRequirement{
-		func() bool {
-			cmd := exec.Command(dockerBinary, "run", "--rm", "busybox", "/bin/sh", "-c", "cat /proc/filesystems")
-			out, err := cmd.CombinedOutput()
-			if err != nil {
-				return false
-			}
-			return bytes.Contains(out, []byte("overlay\n"))
-		},
-		"Test cannot be run without suppport for overlayfs",
-	}
-	overlay2Supported = testRequirement{
-		func() bool {
-			if !overlayFSSupported.Condition() {
-				return false
-			}
-
-			daemonV, err := kernel.ParseRelease(daemonKernelVersion)
-			if err != nil {
-				return false
-			}
-			requiredV := kernel.VersionInfo{Kernel: 4}
-			return kernel.CompareKernelVersion(*daemonV, requiredV) > -1
-
-		},
-		"Test cannot be run without overlay2 support (kernel 4.0+)",
-	}
-)
-
-func init() {
-	SysInfo = sysinfo.New(true)
-}

+ 115 - 0
integration-cli/requirements_unix_test.go

@@ -0,0 +1,115 @@
+// +build !windows
+
+package main
+
+import (
+	"bytes"
+	"io/ioutil"
+	"os/exec"
+	"strings"
+
+	"github.com/docker/docker/pkg/parsers/kernel"
+	"github.com/docker/docker/pkg/sysinfo"
+)
+
+var (
+	// SysInfo stores information about which features a kernel supports.
+	SysInfo *sysinfo.SysInfo
+)
+
+func cpuCfsPeriod() bool {
+	return SysInfo.CPUCfsPeriod
+}
+
+func cpuCfsQuota() bool {
+	return SysInfo.CPUCfsQuota
+}
+
+func cpuShare() bool {
+	return SysInfo.CPUShares
+}
+
+func oomControl() bool {
+	return SysInfo.OomKillDisable
+}
+
+func pidsLimit() bool {
+	return SysInfo.PidsLimit
+}
+
+func kernelMemorySupport() bool {
+	return SysInfo.KernelMemory
+}
+
+func memoryLimitSupport() bool {
+	return SysInfo.MemoryLimit
+}
+
+func memoryReservationSupport() bool {
+	return SysInfo.MemoryReservation
+}
+
+func swapMemorySupport() bool {
+	return SysInfo.SwapLimit
+}
+
+func memorySwappinessSupport() bool {
+	return SysInfo.MemorySwappiness
+}
+
+func blkioWeight() bool {
+	return SysInfo.BlkioWeight
+}
+
+func cgroupCpuset() bool {
+	return SysInfo.Cpuset
+}
+
+func seccompEnabled() bool {
+	return supportsSeccomp && SysInfo.Seccomp
+}
+
+func bridgeNfIptables() bool {
+	return !SysInfo.BridgeNFCallIPTablesDisabled
+}
+
+func bridgeNfIP6tables() bool {
+	return !SysInfo.BridgeNFCallIP6TablesDisabled
+}
+
+func unprivilegedUsernsClone() bool {
+	content, err := ioutil.ReadFile("/proc/sys/kernel/unprivileged_userns_clone")
+	return err != nil || !strings.Contains(string(content), "0")
+}
+
+func ambientCapabilities() bool {
+	content, err := ioutil.ReadFile("/proc/self/status")
+	return err != nil || strings.Contains(string(content), "CapAmb:")
+}
+
+func overlayFSSupported() bool {
+	cmd := exec.Command(dockerBinary, "run", "--rm", "busybox", "/bin/sh", "-c", "cat /proc/filesystems")
+	out, err := cmd.CombinedOutput()
+	if err != nil {
+		return false
+	}
+	return bytes.Contains(out, []byte("overlay\n"))
+}
+
+func overlay2Supported() bool {
+	if !overlayFSSupported() {
+		return false
+	}
+
+	daemonV, err := kernel.ParseRelease(daemonKernelVersion)
+	if err != nil {
+		return false
+	}
+	requiredV := kernel.VersionInfo{Kernel: 4}
+	return kernel.CompareKernelVersion(*daemonV, requiredV) > -1
+
+}
+
+func init() {
+	SysInfo = sysinfo.New(true)
+}