mirror of
				https://github.com/moby/moby.git
				synced 2022-11-09 12:21:53 -05:00 
			
		
		
		
	Merge pull request #29483 from vdemeester/extract-and-refactor-requirement
[test-integration] Refactor and extract TestRequire functionality
This commit is contained in:
		
						commit
						f847a3b7ce
					
				
					 10 changed files with 402 additions and 453 deletions
				
			
		| 
						 | 
				
			
			@ -1665,7 +1665,7 @@ func (s *DockerSuite) TestContainersAPICreateMountsValidation(c *check.C) {
 | 
			
		|||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if SameHostDaemon.Condition() {
 | 
			
		||||
	if SameHostDaemon() {
 | 
			
		||||
		tmpDir, err := ioutils.TempDir("", "test-mounts-api")
 | 
			
		||||
		c.Assert(err, checker.IsNil)
 | 
			
		||||
		defer os.RemoveAll(tmpDir)
 | 
			
		||||
| 
						 | 
				
			
			@ -1696,7 +1696,7 @@ func (s *DockerSuite) TestContainersAPICreateMountsValidation(c *check.C) {
 | 
			
		|||
		}...)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if DaemonIsLinux.Condition() {
 | 
			
		||||
	if DaemonIsLinux() {
 | 
			
		||||
		cases = append(cases, []testCase{
 | 
			
		||||
			{
 | 
			
		||||
				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}},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if SameHostDaemon.Condition() {
 | 
			
		||||
	if SameHostDaemon() {
 | 
			
		||||
		// setup temp dir for testing binds
 | 
			
		||||
		tmpDir1, err := ioutil.TempDir("", "test-mounts-api-1")
 | 
			
		||||
		c.Assert(err, checker.IsNil)
 | 
			
		||||
| 
						 | 
				
			
			@ -1834,7 +1834,7 @@ func (s *DockerSuite) TestContainersAPICreateMountsCreate(c *check.C) {
 | 
			
		|||
		}...)
 | 
			
		||||
 | 
			
		||||
		// for modes only supported on Linux
 | 
			
		||||
		if DaemonIsLinux.Condition() {
 | 
			
		||||
		if DaemonIsLinux() {
 | 
			
		||||
			tmpDir3, err := ioutils.TempDir("", "test-mounts-api-3")
 | 
			
		||||
			c.Assert(err, checker.IsNil)
 | 
			
		||||
			defer os.RemoveAll(tmpDir3)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -289,7 +289,7 @@ func containerStartOutputEquals(c *check.C, containerID, contents string) (err e
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func defaultVolumes(tmpDir string) []string {
 | 
			
		||||
	if SameHostDaemon.Condition() {
 | 
			
		||||
	if SameHostDaemon() {
 | 
			
		||||
		return []string{
 | 
			
		||||
			"/vol1",
 | 
			
		||||
			fmt.Sprintf("%s:/vol2", tmpDir),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -40,7 +40,7 @@ func (s *DockerSuite) TestInfoEnsureSucceeds(c *check.C) {
 | 
			
		|||
		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")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -749,7 +749,7 @@ func (s *DockerSuite) TestPsShowMounts(c *check.C) {
 | 
			
		|||
	// bind mount container
 | 
			
		||||
	var bindMountSource string
 | 
			
		||||
	var bindMountDestination string
 | 
			
		||||
	if DaemonIsWindows.Condition() {
 | 
			
		||||
	if DaemonIsWindows() {
 | 
			
		||||
		bindMountSource = "c:\\"
 | 
			
		||||
		bindMountDestination = "c:\\t"
 | 
			
		||||
	} else {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,44 +13,37 @@ import (
 | 
			
		|||
	"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) {
 | 
			
		||||
	// 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 := "dm-dummy0"
 | 
			
		||||
| 
						 | 
				
			
			@ -70,7 +63,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkMacvlanPersistance(c *check.C) {
 | 
			
		|||
 | 
			
		||||
func (s *DockerNetworkSuite) TestDockerNetworkIpvlanPersistance(c *check.C) {
 | 
			
		||||
	// 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 := "di-dummy0"
 | 
			
		||||
	// 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) {
 | 
			
		||||
	// 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 := "dm-dummy0"
 | 
			
		||||
	// 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) {
 | 
			
		||||
	// 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 := "di-dummy0"
 | 
			
		||||
	// 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) {
 | 
			
		||||
	// 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 := "dm-dummy0"
 | 
			
		||||
	out, err := createMasterDummy(c, master)
 | 
			
		||||
| 
						 | 
				
			
			@ -139,7 +132,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkMacvlanOverlapParent(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
 | 
			
		||||
	testRequires(c, DaemonIsLinux, IpvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
 | 
			
		||||
	testRequires(c, DaemonIsLinux, ipvlanKernelSupport, NotUserNamespace, NotArm, ExperimentalDaemon)
 | 
			
		||||
	// master dummy interface 'dm' abbreviation represents 'docker ipvlan'
 | 
			
		||||
	master := "di-dummy0"
 | 
			
		||||
	out, err := createMasterDummy(c, master)
 | 
			
		||||
| 
						 | 
				
			
			@ -159,7 +152,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkIpvlanOverlapParent(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
 | 
			
		||||
	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",
 | 
			
		||||
		"--subnet=2001:db8:abc2::/64", "--subnet=2001:db8:abc4::/64", "--gateway=2001:db8:abc4::254", "dualstackbridge")
 | 
			
		||||
	// Ensure the network was created
 | 
			
		||||
| 
						 | 
				
			
			@ -214,7 +207,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkMacvlanMultiSubnet(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
 | 
			
		||||
	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",
 | 
			
		||||
		"--subnet=2001:db8:abc8::/64", "--subnet=2001:db8:abc6::/64", "--gateway=2001:db8:abc6::254", "dualstackl2")
 | 
			
		||||
	// Ensure the network was created
 | 
			
		||||
| 
						 | 
				
			
			@ -268,7 +261,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkIpvlanL2MultiSubnet(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
 | 
			
		||||
	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",
 | 
			
		||||
		"--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
 | 
			
		||||
| 
						 | 
				
			
			@ -327,7 +320,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkIpvlanL3MultiSubnet(c *check.C) {
 | 
			
		|||
 | 
			
		||||
func (s *DockerNetworkSuite) TestDockerNetworkIpvlanAddressing(c *check.C) {
 | 
			
		||||
	// 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",
 | 
			
		||||
		"--subnet=2001:db8:abca::/64", "--gateway=2001:db8:abca::254", "-o", "macvlan_mode=bridge", "dualstackbridge")
 | 
			
		||||
	assertNwIsAvailable(c, "dualstackbridge")
 | 
			
		||||
| 
						 | 
				
			
			@ -373,7 +366,7 @@ func (s *DockerNetworkSuite) TestDockerNetworkIpvlanAddressing(c *check.C) {
 | 
			
		|||
 | 
			
		||||
func (s *DockerSuite) TestDockerNetworkMacVlanBridgeNilParent(c *check.C) {
 | 
			
		||||
	// 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")
 | 
			
		||||
	assertNwIsAvailable(c, "dm-nil-parent")
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -390,7 +383,7 @@ func (s *DockerSuite) TestDockerNetworkMacVlanBridgeNilParent(c *check.C) {
 | 
			
		|||
 | 
			
		||||
func (s *DockerSuite) TestDockerNetworkMacVlanBridgeInternalMode(c *check.C) {
 | 
			
		||||
	// 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")
 | 
			
		||||
	assertNwIsAvailable(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) {
 | 
			
		||||
	// 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")
 | 
			
		||||
	assertNwIsAvailable(c, "di-nil-parent")
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -430,7 +423,7 @@ func (s *DockerSuite) TestDockerNetworkIpvlanL2NilParent(c *check.C) {
 | 
			
		|||
 | 
			
		||||
func (s *DockerSuite) TestDockerNetworkIpvlanL2InternalMode(c *check.C) {
 | 
			
		||||
	// 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")
 | 
			
		||||
	assertNwIsAvailable(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) {
 | 
			
		||||
	// 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",
 | 
			
		||||
		"--subnet=172.28.220.0/24", "-o", "ipvlan_mode=l3", "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) {
 | 
			
		||||
	// 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",
 | 
			
		||||
		"--subnet=172.28.220.0/24", "-o", "ipvlan_mode=l3", "--internal", "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) {
 | 
			
		||||
	// 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"
 | 
			
		||||
	out, err := createMasterDummy(c, "dm-dummy0")
 | 
			
		||||
	//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) {
 | 
			
		||||
	// 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"
 | 
			
		||||
	out, err := createMasterDummy(c, "dm-dummy0")
 | 
			
		||||
	c.Assert(err, check.IsNil, check.Commentf(out))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										26
									
								
								integration-cli/requirement/requirement.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								integration-cli/requirement/requirement.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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
									
								
								integration-cli/requirements_test.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										211
									
								
								integration-cli/requirements_test.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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...)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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
									
								
								integration-cli/requirements_unix_test.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								integration-cli/requirements_unix_test.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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)
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue