Ejemplo n.º 1
0
/*
 * Default-restricted net
 * ---
 * Container launches http server on all its interfaces
 * Host must be able to connects to container's http server via container's
 * eth0's IPv4
 * TODO: verify that the container isn't NATed
 */
func TestNetDefaultRestrictedConnectivity(t *testing.T) {
	ctx := newRktRunCtx()
	defer ctx.cleanup()

	f := func(argument string) {
		httpPort, err := testutils.GetNextFreePort4()
		if err != nil {
			t.Fatalf("%v", err)
		}
		httpServeAddr := fmt.Sprintf("0.0.0.0:%v", httpPort)
		iface := "eth0"

		testImageArgs := []string{fmt.Sprintf("--exec=/inspect --print-ipv4=%v --serve-http=%v", iface, httpServeAddr)}
		testImage := patchTestACI("rkt-inspect-networking.aci", testImageArgs...)
		defer os.Remove(testImage)

		cmd := fmt.Sprintf("%s --debug --insecure-skip-verify run %s --mds-register=false %s", ctx.cmd(), argument, testImage)
		child := spawnOrFail(t, cmd)

		expectedRegex := `IPv4: (.*)\r`
		result, out, err := expectRegexWithOutput(child, expectedRegex)
		if err != nil {
			t.Fatalf("Error: %v\nOutput: %v", err, out)
		}
		httpGetAddr := fmt.Sprintf("http://%v:%v", result[1], httpPort)

		ga := testutils.NewGoroutineAssistant(t)
		// Child opens the server
		ga.Add(1)
		go func() {
			defer ga.Done()
			waitOrFail(t, child, true)
		}()

		// Host connects to the child
		ga.Add(1)
		go func() {
			defer ga.Done()
			expectedRegex := `serving on`
			_, out, err := expectRegexWithOutput(child, expectedRegex)
			if err != nil {
				ga.Fatalf("Error: %v\nOutput: %v", err, out)
				return
			}
			body, err := testutils.HttpGet(httpGetAddr)
			if err != nil {
				ga.Fatalf("%v\n", err)
				return
			}
			log.Printf("HTTP-Get received: %s", body)
			if err != nil {
				ga.Fatalf("%v\n", err)
			}
		}()

		ga.Wait()
	}
	f("--net=default-restricted")
	f("--net=none")
}
Ejemplo n.º 2
0
/*
 * Default-restricted private-net
 * ---
 * Container launches http server on all its interfaces
 * Host must be able to connects to container's http server via container's
 * eth0's IPv4
 * TODO: verify that the container isn't NATed
 */
func TestPrivateNetDefaultRestrictedConnectivity(t *testing.T) {
	httpServeAddr := "0.0.0.0:54321"
	iface := "eth0"

	testImageArgs := []string{fmt.Sprintf("--exec=/inspect --print-ipv4=%v --serve-http=%v", iface, httpServeAddr)}
	testImage := patchTestACI("rkt-inspect-networking.aci", testImageArgs...)
	defer os.Remove(testImage)

	ctx := newRktRunCtx()
	defer ctx.cleanup()
	defer ctx.reset()

	cmd := fmt.Sprintf("%s --debug --insecure-skip-verify run --private-net=default-restricted --mds-register=false %s", ctx.cmd(), testImage)
	t.Logf("Command: %v\n", cmd)
	child, err := gexpect.Spawn(cmd)
	if err != nil {
		t.Fatalf("Cannot exec rkt: %v", err)
	}

	expectedRegex := `IPv4: (.*)\r`
	result, out, err := expectRegexWithOutput(child, expectedRegex)
	if err != nil {
		t.Fatalf("Error: %v\nOutput: %v", err, out)
	}
	httpGetAddr := fmt.Sprintf("http://%v:54321", result[1])

	ga := testutils.NewGoroutineAssistant(t)
	// Child opens the server
	ga.Add(1)
	go func() {
		defer ga.Done()
		err = child.Wait()
		if err != nil {
			ga.Fatalf("rkt didn't terminate correctly: %v", err)
		}
	}()

	// Host connects to the child
	ga.Add(1)
	go func() {
		defer ga.Done()
		expectedRegex := `serving on`
		_, out, err := expectRegexWithOutput(child, expectedRegex)
		if err != nil {
			ga.Fatalf("Error: %v\nOutput: %v", err, out)
			return
		}
		body, err := testutils.HttpGet(httpGetAddr)
		if err != nil {
			ga.Fatalf("%v\n", err)
			return
		}
		log.Printf("HTTP-Get received: %s", body)
		if err != nil {
			ga.Fatalf("%v\n", err)
		}
	}()

	ga.Wait()
}
Ejemplo n.º 3
0
// Test that CNI invocations which return DNS information are carried through to /etc/resolv.conf
func NewNetCNIDNSTest() testutils.Test {
	return testutils.TestFunc(func(t *testing.T) {
		ctx := testutils.NewRktRunCtx()
		defer ctx.Cleanup()

		iface, _, err := testutils.GetNonLoIfaceWithAddrs(netlink.FAMILY_V4)
		if err != nil {
			t.Fatalf("Error while getting non-lo host interface: %v\n", err)
		}
		if iface.Name == "" {
			t.Skipf("Cannot run test without non-lo host interface")
		}

		nt := networkTemplateT{
			Name:      "bridge0",
			Type:      "cniproxy",
			Args:      []string{"X_LOG=output.json", "X_REAL_PLUGIN=bridge", "X_ADD_DNS=1"},
			IpMasq:    true,
			IsGateway: true,
			Master:    iface.Name,
			Ipam: &ipamTemplateT{
				Type:   "host-local",
				Subnet: "11.11.3.0/24",
				Routes: []map[string]string{
					{"dst": "0.0.0.0/0"},
				},
			},
		}

		// bring the networking up, copy the proxy
		netdir := prepareTestNet(t, ctx, nt)
		defer os.RemoveAll(netdir)

		ga := testutils.NewGoroutineAssistant(t)
		ga.Add(1)

		go func() {
			defer ga.Done()

			appCmd := "--exec=/inspect -- --read-file --file-name=/etc/resolv.conf"
			cmd := fmt.Sprintf("%s --debug --insecure-options=image run --net=%v --mds-register=false %s %s",
				ctx.Cmd(), nt.NetParameter(), getInspectImagePath(), appCmd)
			child := ga.SpawnOrFail(cmd)
			defer ga.WaitOrFail(child)

			expectedRegex := "nameserver 1.2.3.4"

			_, out, err := expectRegexTimeoutWithOutput(child, expectedRegex, 30*time.Second)
			if err != nil {
				ga.Fatalf("Error: %v\nOutput: %v", err, out)
			}
		}()

		ga.Wait()
	})
}
Ejemplo n.º 4
0
/*
 * Host networking
 * ---
 * Container launches http server which must be reachable by the host via the
 * localhost address
 */
func TestNetHostConnectivity(t *testing.T) {

	httpPort, err := testutils.GetNextFreePort4()
	if err != nil {
		t.Fatalf("%v", err)
	}
	httpServeAddr := fmt.Sprintf("0.0.0.0:%v", httpPort)
	httpGetAddr := fmt.Sprintf("http://127.0.0.1:%v", httpPort)

	testImageArgs := []string{"--exec=/inspect --serve-http=" + httpServeAddr}
	testImage := patchTestACI("rkt-inspect-networking.aci", testImageArgs...)
	defer os.Remove(testImage)

	ctx := newRktRunCtx()
	defer ctx.cleanup()

	cmd := fmt.Sprintf("%s --net=host --debug --insecure-skip-verify run --mds-register=false %s", ctx.cmd(), testImage)
	t.Logf("Command: %v\n", cmd)
	child, err := gexpect.Spawn(cmd)
	if err != nil {
		t.Fatalf("Cannot exec rkt: %v", err)
	}

	ga := testutils.NewGoroutineAssistant(t)
	// Child opens the server
	ga.Add(1)
	go func() {
		defer ga.Done()
		err = child.Wait()
		if err != nil {
			ga.Fatalf("rkt didn't terminate correctly: %v", err)
			return
		}
	}()

	// Host connects to the child
	ga.Add(1)
	go func() {
		defer ga.Done()
		expectedRegex := `serving on`
		_, out, err := expectRegexWithOutput(child, expectedRegex)
		if err != nil {
			ga.Fatalf("Error: %v\nOutput: %v", err, out)
			return
		}
		body, err := testutils.HttpGet(httpGetAddr)
		if err != nil {
			ga.Fatalf("%v\n", err)
			return
		}
		log.Printf("HTTP-Get received: %s", body)
	}()

	ga.Wait()
}
Ejemplo n.º 5
0
/*
 * Host networking
 * ---
 * Container launches http server which must be reachable by the host via the
 * localhost address
 */
func NewNetHostConnectivityTest() testutils.Test {
	return testutils.TestFunc(func(t *testing.T) {
		logger.SetLogger(t)

		httpPort, err := testutils.GetNextFreePort4()
		if err != nil {
			t.Fatalf("%v", err)
		}
		httpServeAddr := fmt.Sprintf("0.0.0.0:%v", httpPort)
		httpGetAddr := fmt.Sprintf("http://127.0.0.1:%v", httpPort)

		testImageArgs := []string{"--exec=/inspect --serve-http=" + httpServeAddr}
		testImage := patchTestACI("rkt-inspect-networking.aci", testImageArgs...)
		defer os.Remove(testImage)

		ctx := testutils.NewRktRunCtx()
		defer ctx.Cleanup()

		cmd := fmt.Sprintf("%s --net=host --debug --insecure-options=image run --mds-register=false %s", ctx.Cmd(), testImage)
		child := spawnOrFail(t, cmd)
		ctx.RegisterChild(child)

		ga := testutils.NewGoroutineAssistant(t)
		ga.Add(2)

		// Child opens the server
		go func() {
			defer ga.Done()
			ga.WaitOrFail(child)
		}()

		// Host connects to the child
		go func() {
			defer ga.Done()
			expectedRegex := `serving on`
			_, out, err := expectRegexWithOutput(child, expectedRegex)
			if err != nil {
				ga.Fatalf("Error: %v\nOutput: %v", err, out)
			}
			body, err := testutils.HTTPGet(httpGetAddr)
			if err != nil {
				ga.Fatalf("%v\n", err)
			}
			t.Logf("HTTP-Get received: %s", body)
		}()

		ga.Wait()
	})
}
Ejemplo n.º 6
0
func TestDBRace(t *testing.T) {
	// TODO(sgotti) this will not find concurrent accesses to ql db from
	// multiple processes using multiple goroutines. A test that spawns at
	// least two processes using multiple goroutines is needed.
	// See https://github.com/coreos/rkt/pull/2391
	oldGoMaxProcs := runtime.GOMAXPROCS(runtime.NumCPU())
	defer runtime.GOMAXPROCS(oldGoMaxProcs)

	dir, err := ioutil.TempDir("", "rkt_db_test")
	if err != nil {
		t.Fatalf("Unexpected error: %v", err)
	}
	defer os.RemoveAll(dir)

	db, err := NewDB(dir)
	if err != nil {
		t.Fatalf("Unexpected error: %v", err)
	}

	// Create the table.
	createTable(db, t)

	// Insert values concurrently.
	ga := testutils.NewGoroutineAssistant(t)
	runs := 100
	ga.Add(runs)
	for i := 0; i < runs; i++ {
		go func() {
			if err := insertValue(db); err != nil {
				ga.Fatalf("Failed to insert value: %v", err)
			}
			ga.Done()
		}()
	}
	ga.Wait()

	// Check the final values.
	maxCount := getMaxCount(db, t)
	if maxCount != runs {
		t.Errorf("Expected: %v, saw: %v", runs, maxCount)
	}
}
Ejemplo n.º 7
0
func TestDBRace(t *testing.T) {
	oldGoMaxProcs := runtime.GOMAXPROCS(runtime.NumCPU())
	defer runtime.GOMAXPROCS(oldGoMaxProcs)

	dir, err := ioutil.TempDir("", "rkt_db_test")
	if err != nil {
		t.Fatalf("Unexpected error: %v", err)
	}
	defer os.RemoveAll(dir)

	db, err := NewDB(dir)
	if err != nil {
		t.Fatalf("Unexpected error: %v", err)
	}

	// Create the table.
	createTable(db, t)

	// Insert values concurrently.
	ga := testutils.NewGoroutineAssistant(t)
	runs := 100
	ga.Add(runs)
	for i := 0; i < runs; i++ {
		go func() {
			if err := insertValue(db); err != nil {
				ga.Fatalf("Failed to insert value: %v", err)
			}
			ga.Done()
		}()
	}
	ga.Wait()

	// Check the final values.
	maxCount := getMaxCount(db, t)
	if maxCount != runs {
		t.Errorf("Expected: %v, saw: %v", runs, maxCount)
	}
}
Ejemplo n.º 8
0
/*
 * Host launches http server on all interfaces in the host netns
 * Container must be able to connect via any IP address of the host in the
 * macvlan network, which is NAT
 * TODO: test connection to host on an outside interface
 */
func testNetCustomNatConnectivity(t *testing.T, nt networkTemplateT) {
	ctx := testutils.NewRktRunCtx()
	defer ctx.Cleanup()

	prepareTestNet(t, ctx, nt)

	httpPort, err := testutils.GetNextFreePort4()
	if err != nil {
		t.Fatalf("%v", err)
	}
	httpServeAddr := fmt.Sprintf("0.0.0.0:%v", httpPort)
	httpServeTimeout := 30

	nonLoIPv4, err := testutils.GetNonLoIfaceIPv4()
	if err != nil {
		t.Fatalf("%v", err)
	}
	if nonLoIPv4 == "" {
		t.Skipf("Can not find any NAT'able IPv4 on the host, skipping..")
	}

	httpGetAddr := fmt.Sprintf("http://%v:%v", nonLoIPv4, httpPort)
	t.Log("Telling the child to connect via", httpGetAddr)

	ga := testutils.NewGoroutineAssistant(t)
	ga.Add(2)

	// Host opens the server
	go func() {
		defer ga.Done()
		err := testutils.HTTPServe(httpServeAddr, httpServeTimeout)
		if err != nil {
			ga.Fatalf("Error during HTTPServe: %v", err)
		}
	}()

	// Child connects to host
	hostname, err := os.Hostname()
	if err != nil {
		panic(err)
	}

	go func() {
		defer ga.Done()
		testImageArgs := []string{fmt.Sprintf("--exec=/inspect --get-http=%v", httpGetAddr)}
		testImage := patchTestACI("rkt-inspect-networking.aci", testImageArgs...)
		defer os.Remove(testImage)

		cmd := fmt.Sprintf("%s --debug --insecure-options=image run --net=%v --mds-register=false %s", ctx.Cmd(), nt.Name, testImage)
		child := ga.SpawnOrFail(cmd)
		defer ga.WaitOrFail(child)

		expectedRegex := `HTTP-Get received: (.*?)\r`
		result, out, err := expectRegexWithOutput(child, expectedRegex)
		if err != nil {
			ga.Fatalf("Error: %v\nOutput: %v", err, out)
		}

		if result[1] != hostname {
			ga.Fatalf("Hostname received by client `%v` doesn't match `%v`", result[1], hostname)
		}
	}()

	ga.Wait()
}
Ejemplo n.º 9
0
/*
 * Two containers spawn in the same custom network.
 * ---
 * Container 1 opens the http server
 * Container 2 fires a HTTPGet on it
 * The body of the HTTPGet is Container 1's hostname, which must match
 */
func testNetCustomDual(t *testing.T, nt networkTemplateT) {
	httpPort, err := testutils.GetNextFreePort4()
	if err != nil {
		t.Fatalf("%v", err)
	}

	ctx := testutils.NewRktRunCtx()
	defer ctx.Cleanup()

	prepareTestNet(t, ctx, nt)

	container1IPv4, container1Hostname := make(chan string), make(chan string)
	ga := testutils.NewGoroutineAssistant(t)
	ga.Add(2)

	go func() {
		defer ga.Done()
		httpServeAddr := fmt.Sprintf("0.0.0.0:%v", httpPort)
		testImageArgs := []string{"--exec=/inspect --print-ipv4=eth0 --serve-http=" + httpServeAddr}
		testImage := patchTestACI("rkt-inspect-networking1.aci", testImageArgs...)
		defer os.Remove(testImage)

		cmd := fmt.Sprintf("%s --debug --insecure-options=image run --net=%v --mds-register=false %s", ctx.Cmd(), nt.Name, testImage)
		child := ga.SpawnOrFail(cmd)
		defer ga.WaitOrFail(child)

		expectedRegex := `IPv4: (\d+\.\d+\.\d+\.\d+)`
		result, out, err := expectRegexTimeoutWithOutput(child, expectedRegex, 30*time.Second)
		if err != nil {
			ga.Fatalf("Error: %v\nOutput: %v", err, out)
		}
		container1IPv4 <- result[1]
		expectedRegex = ` ([a-zA-Z0-9\-]*): serving on`
		result, out, err = expectRegexTimeoutWithOutput(child, expectedRegex, 30*time.Second)
		if err != nil {
			ga.Fatalf("Error: %v\nOutput: %v", err, out)
		}
		container1Hostname <- result[1]
	}()

	go func() {
		defer ga.Done()

		var httpGetAddr string
		httpGetAddr = fmt.Sprintf("http://%v:%v", <-container1IPv4, httpPort)

		testImageArgs := []string{"--exec=/inspect --get-http=" + httpGetAddr}
		testImage := patchTestACI("rkt-inspect-networking2.aci", testImageArgs...)
		defer os.Remove(testImage)

		cmd := fmt.Sprintf("%s --debug --insecure-options=image run --net=%v --mds-register=false %s", ctx.Cmd(), nt.Name, testImage)
		child := ga.SpawnOrFail(cmd)
		defer ga.WaitOrFail(child)

		expectedHostname := <-container1Hostname
		expectedRegex := `HTTP-Get received: (.*?)\r`
		result, out, err := expectRegexTimeoutWithOutput(child, expectedRegex, 20*time.Second)
		if err != nil {
			ga.Fatalf("Error: %v\nOutput: %v", err, out)
		}
		t.Logf("HTTP-Get received: %s", result[1])
		receivedHostname := result[1]

		if receivedHostname != expectedHostname {
			ga.Fatalf("Received hostname `%v` doesn't match `%v`", receivedHostname, expectedHostname)
		}
	}()

	ga.Wait()
}
Ejemplo n.º 10
0
func (ct PortFwdCase) Execute(t *testing.T) {
	ctx := testutils.NewRktRunCtx()
	defer ctx.Cleanup()

	prepareTestNet(t, ctx, portFwdBridge)

	httpPort, err := testutils.GetNextFreePort4Banned(bannedPorts)
	if err != nil {
		t.Fatalf("%v", err)
	}
	bannedPorts[httpPort] = struct{}{}

	httpServePort := ct.HttpServePort
	if httpServePort == 0 {
		httpServePort = httpPort
	}

	httpServeAddr := fmt.Sprintf("0.0.0.0:%d", httpServePort)
	testImageArgs := []string{
		fmt.Sprintf("--ports=http,protocol=tcp,port=%d", httpServePort),
		fmt.Sprintf("--exec=/inspect --serve-http=%v", httpServeAddr),
	}
	t.Logf("testImageArgs: %v", testImageArgs)
	testImage := patchTestACI("rkt-inspect-networking.aci", testImageArgs...)
	defer os.Remove(testImage)

	cmd := fmt.Sprintf(
		"%s --debug --insecure-options=image run --port=http:%s%d %s --mds-register=false %s",
		ctx.Cmd(), ct.ListenAddress, httpPort, ct.RktArg, testImage)
	child := spawnOrFail(t, cmd)

	httpGetAddr := fmt.Sprintf("http://%v:%v", ct.HttpGetIP, httpPort)

	ga := testutils.NewGoroutineAssistant(t)
	ga.Add(2)

	// Child opens the server
	go func() {
		defer ga.Done()
		ga.WaitOrFail(child)
	}()

	// Host connects to the child via the forward port on localhost
	go func() {
		defer ga.Done()
		expectedRegex := `serving on`
		_, out, err := expectRegexWithOutput(child, expectedRegex)
		if err != nil {
			ga.Fatalf("Error: %v\nOutput: %v", err, out)
		}
		body, err := testutils.HTTPGet(httpGetAddr)
		switch {
		case err != nil && ct.ShouldSucceed:
			ga.Fatalf("%v\n", err)
		case err == nil && !ct.ShouldSucceed:
			ga.Fatalf("HTTP-Get to %q should have failed! But received %q", httpGetAddr, body)
		case err != nil && !ct.ShouldSucceed:
			t.Logf("HTTP-Get failed, as expected: %v", err)
		default:
			t.Logf("HTTP-Get received: %s", body)
		}
	}()

	ga.Wait()
}
Ejemplo n.º 11
0
/*
 * Host launches http server on all interfaces in the host netns
 * Container must be able to connect via any IP address of the host in the
 * macvlan network, which is NAT
 * TODO: test connection to host on an outside interface
 */
func testPrivateNetCustomNatConnectivity(t *testing.T, nt networkTemplateT) {
	ctx := newRktRunCtx()
	defer ctx.cleanup()
	defer ctx.reset()

	netdir := prepareTestNet(t, ctx, nt)
	defer os.RemoveAll(netdir)

	httpPort, err := testutils.GetNextFreePort4()
	if err != nil {
		t.Fatalf("%v", err)
	}
	httpServeAddr := fmt.Sprintf("0.0.0.0:%v", httpPort)
	httpServeTimeout := 30

	nonLoIPv4, err := testutils.GetNonLoIfaceIPv4()
	if err != nil {
		t.Fatalf("%v", err)
	}
	if nonLoIPv4 == "" {
		t.Skipf("Can not find any NAT'able IPv4 on the host, skipping..")
	}

	httpGetAddr := fmt.Sprintf("http://%v:%v", nonLoIPv4, httpPort)
	t.Log("Telling the child to connect via", httpGetAddr)

	ga := testutils.NewGoroutineAssistant(t)

	// Host opens the server
	ga.Add(1)
	go func() {
		defer ga.Done()
		err := testutils.HttpServe(httpServeAddr, httpServeTimeout)
		if err != nil {
			t.Fatalf("Error during HttpServe: %v", err)
		}
	}()

	// Child connects to host
	ga.Add(1)
	hostname, err := os.Hostname()
	go func() {
		defer ga.Done()
		testImageArgs := []string{fmt.Sprintf("--exec=/inspect --get-http=%v", httpGetAddr)}
		testImage := patchTestACI("rkt-inspect-networking.aci", testImageArgs...)
		defer os.Remove(testImage)

		cmd := fmt.Sprintf("%s --debug --insecure-skip-verify run --private-net=%v --mds-register=false %s", ctx.cmd(), nt.Name, testImage)
		t.Logf("Command: %v\n", cmd)
		child, err := gexpect.Spawn(cmd)
		if err != nil {
			ga.Fatalf("Cannot exec rkt: %v", err)
			return
		}
		expectedRegex := `HTTP-Get received: (.*)\r`
		result, out, err := expectRegexWithOutput(child, expectedRegex)
		if err != nil {
			ga.Fatalf("Error: %v\nOutput: %v", err, out)
			return
		}
		if result[1] != hostname {
			ga.Fatalf("Hostname received by client `%v` doesn't match `%v`", result[1], hostname)
			return
		}

		err = child.Wait()
		if err != nil {
			ga.Fatalf("rkt didn't terminate correctly: %v", err)
		}
	}()

	ga.Wait()
}
Ejemplo n.º 12
0
/*
 * Two containers spawn in the same custom network.
 * ---
 * Container 1 opens the http server
 * Container 2 fires a HttpGet on it
 * The body of the HttpGet is Container 1's hostname, which must match
 */
func testPrivateNetCustomDual(t *testing.T, nt networkTemplateT) {
	httpPort, err := testutils.GetNextFreePort4()
	if err != nil {
		t.Fatalf("%v", err)
	}

	ctx := newRktRunCtx()
	defer ctx.cleanup()
	defer ctx.reset()

	netdir := prepareTestNet(t, ctx, nt)
	defer os.RemoveAll(netdir)

	container1IPv4, container1Hostname := make(chan string), make(chan string)
	ga := testutils.NewGoroutineAssistant(t)

	ga.Add(1)
	go func() {
		defer ga.Done()
		httpServeAddr := fmt.Sprintf("0.0.0.0:%v", httpPort)
		testImageArgs := []string{"--exec=/inspect --print-ipv4=eth0 --serve-http=" + httpServeAddr}
		testImage := patchTestACI("rkt-inspect-networking1.aci", testImageArgs...)
		defer os.Remove(testImage)

		cmd := fmt.Sprintf("%s --debug --insecure-skip-verify run --private-net=%v --mds-register=false %s", ctx.cmd(), nt.Name, testImage)
		fmt.Printf("Command: %v\n", cmd)
		child, err := gexpect.Spawn(cmd)
		if err != nil {
			ga.Fatalf("Cannot exec rkt: %v", err)
			return
		}

		expectedRegex := `IPv4: (\d+\.\d+\.\d+\.\d+)`
		result, out, err := expectRegexTimeoutWithOutput(child, expectedRegex, 30*time.Second)
		if err != nil {
			ga.Fatalf("Error: %v\nOutput: %v", err, out)
			return
		}
		container1IPv4 <- result[1]
		expectedRegex = `(rkt-.*): serving on`
		result, out, err = expectRegexTimeoutWithOutput(child, expectedRegex, 30*time.Second)
		if err != nil {
			ga.Fatalf("Error: %v\nOutput: %v", err, out)
			return
		}
		container1Hostname <- result[1]

		err = child.Wait()
		if err != nil {
			ga.Fatalf("rkt didn't terminate correctly: %v", err)
		}
	}()

	ga.Add(1)
	go func() {
		defer ga.Done()

		var httpGetAddr string
		httpGetAddr = fmt.Sprintf("http://%v:%v", <-container1IPv4, httpPort)

		testImageArgs := []string{"--exec=/inspect --get-http=" + httpGetAddr}
		testImage := patchTestACI("rkt-inspect-networking2.aci", testImageArgs...)
		defer os.Remove(testImage)

		cmd := fmt.Sprintf("%s --debug --insecure-skip-verify run --private-net=%v --mds-register=false %s", ctx.cmd(), nt.Name, testImage)
		fmt.Printf("Command: %v\n", cmd)
		child, err := gexpect.Spawn(cmd)
		if err != nil {
			t.Fatalf("Cannot exec rkt: %v", err)
		}

		expectedHostname := <-container1Hostname
		expectedRegex := `HTTP-Get received: (.*)\r`
		result, out, err := expectRegexTimeoutWithOutput(child, expectedRegex, 20*time.Second)
		if err != nil {
			ga.Fatalf("Error: %v\nOutput: %v", err, out)
			return
		}
		t.Logf("HTTP-Get received: %s", result[1])
		receivedHostname := result[1]

		if receivedHostname != expectedHostname {
			ga.Fatalf("Received hostname `%v` doesn't match `%v`", receivedHostname, expectedHostname)
			return
		}

		err = child.Wait()
		if err != nil {
			ga.Fatalf("rkt didn't terminate correctly: %v", err)
		}
	}()

	ga.Wait()
}
Ejemplo n.º 13
0
//Test that the CNI execution environment matches the spec
func NewNetCNIEnvTest() testutils.Test {
	return testutils.TestFunc(func(t *testing.T) {
		ctx := testutils.NewRktRunCtx()
		defer ctx.Cleanup()

		iface, _, err := testutils.GetNonLoIfaceWithAddrs(netlink.FAMILY_V4)
		if err != nil {
			t.Fatalf("Error while getting non-lo host interface: %v\n", err)
		}
		if iface.Name == "" {
			t.Skipf("Cannot run test without non-lo host interface")
		}

		// Declares a network of type cniproxy, which will record state and
		// proxy through to $X_REAL_PLUGIN
		nt := networkTemplateT{
			Name:      "bridge0",
			Type:      "cniproxy",
			Args:      []string{"X_LOG=output.json", "X_REAL_PLUGIN=bridge"},
			IpMasq:    true,
			IsGateway: true,
			Master:    iface.Name,
			Ipam: &ipamTemplateT{
				Type:   "host-local",
				Subnet: "11.11.3.0/24",
				Routes: []map[string]string{
					{"dst": "0.0.0.0/0"},
				},
			},
		}

		// bring the networking up, copy the proxy
		netdir := prepareTestNet(t, ctx, nt)
		defer os.RemoveAll(netdir)

		ga := testutils.NewGoroutineAssistant(t)
		ga.Add(1)

		go func() {
			defer ga.Done()
			appCmd := "--exec=/inspect -- --print-defaultgwv4 "
			cmd := fmt.Sprintf("%s --debug --insecure-options=image run --net=%v --mds-register=false %s %s",
				ctx.Cmd(), nt.NetParameter(), getInspectImagePath(), appCmd)
			child := ga.SpawnOrFail(cmd)
			defer ga.WaitOrFail(child)

			expectedRegex := "DefaultGWv4: 11.11.3.1"

			_, out, err := expectRegexTimeoutWithOutput(child, expectedRegex, 30*time.Second)
			if err != nil {
				ga.Fatalf("Error: %v\nOutput: %v", err, out)
			}
		}()

		ga.Wait()

		// Parse the log file
		proxyLog, err := parseCNIProxyLog(filepath.Join(netdir, "output.json"))
		if err != nil {
			t.Fatal("Failed to read cniproxy log", err)
		}

		// Check that the stdin matches the network config file
		expectedConfig, err := ioutil.ReadFile(filepath.Join(netdir, nt.Name+".conf"))
		if err != nil {
			t.Fatal("Failed to read network configuration", err)
		}

		if string(expectedConfig) != proxyLog.Stdin {
			t.Fatalf("CNI plugin stdin incorrect, expected <<%v>>, actual <<%v>>", expectedConfig, proxyLog.Stdin)
		}

		// Check that the environment is sane - these are regexes
		expectedEnv := map[string]string{
			"CNI_VERSION":     "0.3.0",
			"CNI_COMMAND":     "ADD",
			"CNI_IFNAME":      `eth\d`,
			"CNI_PATH":        netdir,
			"CNI_NETNS":       `/var/run/netns/cni-`,
			"CNI_CONTAINERID": `^[a-fA-F0-9-]{36}`, //UUID, close enough
		}

		for k, v := range expectedEnv {
			actual, exists := proxyLog.EnvMap[k]
			if !exists {
				t.Fatalf("Expected proxy CNI arg %s but not found", k)
			}

			re, err := regexp.Compile(v)
			if err != nil {
				t.Fatal("Invalid CNI env regex", v, err)
			}
			found := re.FindString(actual)
			if found == "" {
				t.Fatalf("CNI_ARG %s was %s but expected pattern %s", k, actual, v)
			}
		}
	})
}
Ejemplo n.º 14
0
/*
 * Default net port forwarding connectivity
 * ---
 * Container launches http server on all its interfaces
 * Host must be able to connect to container's http server on it's own interfaces
 */
func TestNetDefaultPortFwdConnectivity(t *testing.T) {
	ctx := testutils.NewRktRunCtx()
	defer ctx.Cleanup()

	bannedPorts := make(map[int]struct{}, 0)
	f := func(httpGetIP string, rktArg string, shouldSucceed bool) {
		httpPort, err := testutils.GetNextFreePort4Banned(bannedPorts)
		if err != nil {
			t.Fatalf("%v", err)
		}
		bannedPorts[httpPort] = struct{}{}

		httpServeAddr := fmt.Sprintf("0.0.0.0:%d", httpPort)
		testImageArgs := []string{
			fmt.Sprintf("--ports=http,protocol=tcp,port=%d", httpPort),
			fmt.Sprintf("--exec=/inspect --serve-http=%v", httpServeAddr),
		}
		testImage := patchTestACI("rkt-inspect-networking.aci", testImageArgs...)
		defer os.Remove(testImage)

		cmd := fmt.Sprintf(
			"%s --debug --insecure-options=image run --port=http:%d %s --mds-register=false %s",
			ctx.Cmd(), httpPort, rktArg, testImage)
		child := spawnOrFail(t, cmd)

		httpGetAddr := fmt.Sprintf("http://%v:%v", httpGetIP, httpPort)

		ga := testutils.NewGoroutineAssistant(t)
		ga.Add(2)

		// Child opens the server
		go func() {
			defer ga.Done()
			ga.WaitOrFail(child)
		}()

		// Host connects to the child via the forward port on localhost
		go func() {
			defer ga.Done()
			expectedRegex := `serving on`
			_, out, err := expectRegexWithOutput(child, expectedRegex)
			if err != nil {
				ga.Fatalf("Error: %v\nOutput: %v", err, out)
			}
			body, err := testutils.HTTPGet(httpGetAddr)
			switch {
			case err != nil && shouldSucceed:
				ga.Fatalf("%v\n", err)
			case err == nil && !shouldSucceed:
				ga.Fatalf("HTTP-Get to %q should have failed! But received %q", httpGetAddr, body)
			case err != nil && !shouldSucceed:
				child.Close()
				fallthrough
			default:
				t.Logf("HTTP-Get received: %s", body)
			}
		}()

		ga.Wait()
	}
	f("172.16.28.1", "--net=default", true)
	f("127.0.0.1", "--net=default", true)

	// TODO: ensure that default-restricted is not accessible from non-host
	// f("172.16.28.1", "--net=default-restricted", true)
	// f("127.0.0.1", "--net=default-restricted", true)
}
Ejemplo n.º 15
0
/*
 * Default net
 * ---
 * Host launches http server on all interfaces in the host netns
 * Container must be able to connect via any IP address of the host in the
 * default network, which is NATed
 * TODO: test connection to host on an outside interface
 */
func TestNetDefaultConnectivity(t *testing.T) {
	ctx := newRktRunCtx()
	defer ctx.cleanup()

	f := func(argument string) {
		httpPort, err := testutils.GetNextFreePort4()
		if err != nil {
			t.Fatalf("%v", err)
		}
		httpServeAddr := fmt.Sprintf("0.0.0.0:%v", httpPort)
		httpServeTimeout := 30

		nonLoIPv4, err := testutils.GetNonLoIfaceIPv4()
		if err != nil {
			t.Fatalf("%v", err)
		}
		if nonLoIPv4 == "" {
			t.Skipf("Can not find any NAT'able IPv4 on the host, skipping..")
		}

		httpGetAddr := fmt.Sprintf("http://%v:%v", nonLoIPv4, httpPort)
		t.Log("Telling the child to connect via", httpGetAddr)

		testImageArgs := []string{fmt.Sprintf("--exec=/inspect --get-http=%v", httpGetAddr)}
		testImage := patchTestACI("rkt-inspect-networking.aci", testImageArgs...)
		defer os.Remove(testImage)
		ga := testutils.NewGoroutineAssistant(t)

		// Host opens the server
		ga.Add(1)
		go func() {
			defer ga.Done()
			err := testutils.HttpServe(httpServeAddr, httpServeTimeout)
			if err != nil {
				ga.Fatalf("Error during HttpServe: %v", err)
			}
		}()

		// Child connects to host
		ga.Add(1)
		hostname, err := os.Hostname()
		if err != nil {
			ga.Fatalf("Error getting hostname: %v", err)
		}
		go func() {
			defer ga.Done()
			cmd := fmt.Sprintf("%s --debug --insecure-skip-verify run %s --mds-register=false %s", ctx.cmd(), argument, testImage)
			child := spawnOrFail(t, cmd)
			defer waitOrFail(t, child, true)

			expectedRegex := `HTTP-Get received: (.*)\r`
			result, out, err := expectRegexWithOutput(child, expectedRegex)
			if err != nil {
				ga.Fatalf("Error: %v\nOutput: %v", err, out)
				return
			}
			if result[1] != hostname {
				ga.Fatalf("Hostname received by client `%v` doesn't match `%v`", result[1], hostname)
				return
			}
		}()

		ga.Wait()
	}
	f("--net=default")
	f("")
}
Ejemplo n.º 16
0
/*
 * Default private-net
 * ---
 * Host launches http server on all interfaces in the host netns
 * Container must be able to connect via any IP address of the host in the
 * default network, which is NATed
 */
func TestPrivateNetDefaultConnectivity(t *testing.T) {
	httpServeAddr := "0.0.0.0:54321"
	httpServeTimeout := 30

	ifaces, err := net.Interfaces()
	if err != nil {
		t.Fatalf("Cannot get network host's interfaces: %v", err)
	}
	var httpGetAddr string
	for _, iface := range ifaces[1:] {
		name := iface.Name
		ifaceIPsv4, err := testutils.GetIPsv4(name)
		if err != nil {
			t.Fatalf("Cannot get IPV4 address for interface %v: %v", name, err)
		}
		if len(ifaceIPsv4) > 0 {
			httpGetAddr = fmt.Sprintf("http://%v:54321", ifaceIPsv4[0])
			t.Log("Telling the child to connect via", httpGetAddr)
			break
		}
	}
	if httpGetAddr == "" {
		t.Skipf("Can not find any NAT'able IPv4 on the host, skipping..")
	}

	testImageArgs := []string{fmt.Sprintf("--exec=/inspect --get-http=%v", httpGetAddr)}
	testImage := patchTestACI("rkt-inspect-networking.aci", testImageArgs...)
	defer os.Remove(testImage)

	ctx := newRktRunCtx()
	defer ctx.cleanup()
	defer ctx.reset()

	ga := testutils.NewGoroutineAssistant(t)

	// Host opens the server
	ga.Add(1)
	go func() {
		defer ga.Done()
		err := testutils.HttpServe(httpServeAddr, httpServeTimeout)
		if err != nil {
			t.Fatalf("Error during HttpServe: %v", err)
		}
	}()

	// Child connects to host
	ga.Add(1)
	hostname, err := os.Hostname()
	go func() {
		defer ga.Done()
		cmd := fmt.Sprintf("%s --debug --insecure-skip-verify run --private-net=default --mds-register=false %s", ctx.cmd(), testImage)
		t.Logf("Command: %v\n", cmd)
		child, err := gexpect.Spawn(cmd)
		if err != nil {
			ga.Fatalf("Cannot exec rkt: %v", err)
			return
		}
		expectedRegex := `HTTP-Get received: (.*)\r`
		result, out, err := expectRegexWithOutput(child, expectedRegex)
		if err != nil {
			ga.Fatalf("Error: %v\nOutput: %v", err, out)
			return
		}
		if result[1] != hostname {
			ga.Fatalf("Hostname received by client `%v` doesn't match `%v`", result[1], hostname)
			return
		}

		err = child.Wait()
		if err != nil {
			ga.Fatalf("rkt didn't terminate correctly: %v", err)
		}
	}()

	ga.Wait()
}