Example #1
0
// TestImplicitFetch tests that 'rkt run/prepare' will always bypass the on-disk store
// if the tag is "latest".
func TestImplicitFetch(t *testing.T) {
	foundMsg := "found image in local store"

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

	// 1. Fetch the image.
	// TODO(yifan): Add other ACI with different schemes.
	importImageAndFetchHash(t, ctx, "docker://busybox:ubuntu-12.04")
	importImageAndFetchHash(t, ctx, "docker://busybox:latest")

	// 2. Try run/prepare with specified tag, should get the $foundMsg.
	cmds := []string{
		fmt.Sprintf("%s --insecure-skip-verify run --mds-register=false docker://busybox:ubuntu-12.04", ctx.cmd()),
		fmt.Sprintf("%s --insecure-skip-verify prepare docker://busybox:ubuntu-12.04", ctx.cmd()),
	}

	for _, cmd := range cmds {
		t.Logf("Running test %v", cmd)

		child, err := gexpect.Spawn(cmd)
		if err != nil {
			t.Fatalf("Cannot exec rkt: %v", err)
		}

		if err := child.Expect(foundMsg); err != nil {
			t.Fatalf("Expected %q but not found: %v", foundMsg, err)
		}

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

	// 3. Try run/prepare with/without tag ':latest', should not get $foundMsg.
	cmds = []string{
		fmt.Sprintf("%s --insecure-skip-verify run --mds-register=false docker://busybox", ctx.cmd()),
		fmt.Sprintf("%s --insecure-skip-verify run --mds-register=false docker://busybox", ctx.cmd()),
		fmt.Sprintf("%s --insecure-skip-verify prepare docker://busybox:latest", ctx.cmd()),
		fmt.Sprintf("%s --insecure-skip-verify prepare docker://busybox:latest", ctx.cmd()),
	}

	for _, cmd := range cmds {
		t.Logf("Running test %v", cmd)

		child, err := gexpect.Spawn(cmd)
		if err != nil {
			t.Fatalf("Cannot exec rkt: %v", err)
		}
		if err := child.Expect(foundMsg); err == nil {
			t.Fatalf("%q should not be found", foundMsg)
		}
		if err := child.Wait(); err != nil {
			t.Fatalf("rkt didn't terminate correctly: %v", err)
		}
	}
}
Example #2
0
// TestRunPrepareLocal tests that 'rkt run/prepare' will only use the on-disk store if flag is --local
func TestRunPrepareLocal(t *testing.T) {
	notAvailableMsg := "not available in local store"
	foundMsg := "using image in local store"

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

	cmds := []string{
		fmt.Sprintf("%s --insecure-skip-verify run --local --mds-register=false docker://busybox", ctx.cmd()),
		fmt.Sprintf("%s --insecure-skip-verify run --local --mds-register=false docker://busybox:latest", ctx.cmd()),
		fmt.Sprintf("%s --insecure-skip-verify prepare --local docker://busybox", ctx.cmd()),
		fmt.Sprintf("%s --insecure-skip-verify prepare --local docker://busybox:latest", ctx.cmd()),
	}

	// 1. Try run/prepare with the image not available in the store, should get $notAvailableMsg.
	for _, cmd := range cmds {
		t.Logf("Running test %v", cmd)

		child, err := gexpect.Spawn(cmd)
		if err != nil {
			t.Fatalf("Cannot exec rkt: %v", err)
		}
		if err := expectWithOutput(child, notAvailableMsg); err != nil {
			t.Fatalf("%q should be found", notAvailableMsg)
		}
		child.Wait()
	}

	// 2. Fetch the image
	importImageAndFetchHash(t, ctx, "docker://busybox")
	importImageAndFetchHash(t, ctx, "docker://busybox:latest")

	// 3. Try run/prepare with the image available in the store, should get $foundMsg.
	for _, cmd := range cmds {
		t.Logf("Running test %v", cmd)

		child, err := gexpect.Spawn(cmd)
		if err != nil {
			t.Fatalf("Cannot exec rkt: %v", err)
		}
		if err := expectWithOutput(child, foundMsg); err != nil {
			t.Fatalf("%q should be found", foundMsg)
		}
		if err := child.Wait(); err != nil {
			t.Fatalf("rkt didn't terminate correctly: %v", err)
		}
	}
}
Example #3
0
func TestSuccess(t *testing.T) {
	patchTestACI("rkt-inspect-exit0.aci", "--exec=/inspect --print-msg=Hello --exit-code=0")
	defer os.Remove("rkt-inspect-exit0.aci")
	ctx := newRktRunCtx()
	defer ctx.cleanup()

	child, err := gexpect.Spawn(fmt.Sprintf("%s --debug --insecure-skip-verify run ./rkt-inspect-exit0.aci", ctx.cmd()))
	if err != nil {
		t.Fatalf("Cannot exec rkt")
	}
	err = child.Expect("Hello")
	if err != nil {
		t.Fatalf("Missing hello")
	}
	forbidden := "main process exited, code=exited, status="
	_, receiver := child.AsyncInteractChannels()
	for {
		msg, open := <-receiver
		if !open {
			break
		}
		if strings.Contains(msg, forbidden) {
			t.Fatalf("Forbidden text received")
		}
	}

	err = child.Wait()
	if err != nil {
		t.Fatalf("rkt didn't terminate correctly: %v", err)
	}
}
Example #4
0
func TestExitCode(t *testing.T) {
	for i := 0; i < 3; i++ {
		t.Logf("%d\n", i)
		imageFile := patchTestACI("rkt-inspect-exit.aci", fmt.Sprintf("--exec=/inspect --print-msg=Hello --exit-code=%d", i))
		defer os.Remove(imageFile)
		ctx := newRktRunCtx()
		defer ctx.cleanup()

		cmd := fmt.Sprintf(`/bin/sh -c "`+
			`%s --debug --insecure-skip-verify run --mds-register=false %s ;`+
			`UUID=$(%s list --full|grep exited|awk '{print $1}') ;`+
			`echo -n 'status=' ;`+
			`%s status $UUID|grep '^rkt-inspect.*=[0-9]*$'|cut -d= -f2"`,
			ctx.cmd(), imageFile,
			ctx.cmd(),
			ctx.cmd())
		t.Logf("%s\n", cmd)
		child, err := gexpect.Spawn(cmd)
		if err != nil {
			t.Fatalf("Cannot exec rkt")
		}

		err = expectWithOutput(child, fmt.Sprintf("status=%d", i))
		if err != nil {
			t.Fatalf("Failed to get the status")
		}

		err = child.Wait()
		if err != nil {
			t.Fatalf("rkt didn't terminate correctly: %v", err)
		}
	}
}
Example #5
0
func TestAppIsolatorCPU(t *testing.T) {
	ok := cgroup.IsIsolatorSupported("cpu")
	if !ok {
		t.Skip("CPU isolator not supported.")
	}

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

	t.Logf("Running test: %v", cpuTest.testName)

	aciFileName := patchTestACI("rkt-inspect-isolators.aci", cpuTest.aciBuildArgs...)
	defer os.Remove(aciFileName)

	rktCmd := fmt.Sprintf("%s --insecure-skip-verify run --mds-register=false %s", ctx.cmd(), aciFileName)
	t.Logf("Command: %v", rktCmd)
	child, err := gexpect.Spawn(rktCmd)
	if err != nil {
		t.Fatalf("Cannot exec rkt: %v", err)
	}
	expectedLine := "CPU Quota: " + strconv.Itoa(CPUQuota)
	if err := expectWithOutput(child, expectedLine); err != nil {
		t.Fatalf("Didn't receive expected output %q: %v", expectedLine, err)
	}

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

}
Example #6
0
func TestCgroups(t *testing.T) {
	ctx := newRktRunCtx()
	defer ctx.cleanup()

	t.Logf("Running test: %v", cgroupsTest.testName)

	aciFileName := patchTestACI("rkt-inspect-isolators.aci", cgroupsTest.aciBuildArgs...)
	defer os.Remove(aciFileName)

	rktCmd := fmt.Sprintf("%s --insecure-skip-verify run --mds-register=false %s", ctx.cmd(), aciFileName)
	t.Logf("Command: %v", rktCmd)
	child, err := gexpect.Spawn(rktCmd)
	if err != nil {
		t.Fatalf("Cannot exec rkt: %v", err)
	}
	expectedLine := "check-cgroups: SUCCESS"
	if err := expectWithOutput(child, expectedLine); err != nil {
		t.Fatalf("Didn't receive expected output %q: %v", expectedLine, err)
	}

	err = child.Wait()
	if err != nil {
		t.Fatalf("rkt didn't terminate correctly: %v", err)
	}
}
func TestAppIsolatorMemory(t *testing.T) {
	ok := cgroup.IsIsolatorSupported("memory")
	if !ok {
		t.Skip("Memory isolator not supported.")
	}

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

	t.Logf("Running test: %v", memoryTest.testName)

	aciFileName := "rkt-inspect-isolators.aci"
	patchTestACI(aciFileName, memoryTest.aciBuildArgs...)
	defer os.Remove(aciFileName)

	rktCmd := fmt.Sprintf("%s %s", ctx.cmd(), memoryTest.rktArgs)
	t.Logf("Command: %v", rktCmd)
	child, err := gexpect.Spawn(rktCmd)
	if err != nil {
		t.Fatalf("Cannot exec rkt: %v", err)
	}
	expectedLine := "Memory Limit: " + strconv.Itoa(maxMemoryUsage)
	if err := expectWithOutput(child, expectedLine); err != nil {
		t.Fatalf("Didn't receive expected output %q: %v", expectedLine, err)
	}

	err = child.Wait()
	if err != nil {
		t.Fatalf("rkt didn't terminate correctly: %v", err)
	}
}
Example #8
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", cmd)
	child, err := gexpect.Spawn(cmd)
	if err != nil {
		t.Fatalf("Cannot exec rkt: %v", err)
	}

	expectedRegex := `IPv4: (.*)\r`
	result, _ := child.ExpectRegexFind(expectedRegex)
	if len(result) == 0 {
		t.Fatalf("Expected %q but not found", expectedRegex)
	}
	httpGetAddr := fmt.Sprintf("http://%v:54321", result[1])

	var wg sync.WaitGroup

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

	// Host connects to the child
	wg.Add(1)
	go func() {
		defer wg.Done()
		expectedRegex := `serving on`
		result, _ := child.ExpectRegexFind(expectedRegex)
		if len(result) == 0 {
			t.Fatalf("Expected %q but not found", expectedRegex)
		}
		body, err := test_netutils.HttpGet(httpGetAddr)
		if err != nil {
			log.Fatalf("%v\n", err)
		}
		log.Printf("HTTP-Get received: %s", body)
		if err != nil {
			log.Fatalf("%v\n", err)
		}
	}()

	wg.Wait()
}
Example #9
0
func preparePidFileRace(t *testing.T, ctx *rktRunCtx, sleepImage string) (*gexpect.ExpectSubprocess, *gexpect.ExpectSubprocess, string, string) {
	// Start the pod
	runCmd := fmt.Sprintf("%s --debug --insecure-skip-verify run --mds-register=false --interactive %s", ctx.cmd(), sleepImage)
	t.Logf("%s", runCmd)
	runChild, err := gexpect.Spawn(runCmd)
	if err != nil {
		t.Fatalf("Cannot exec rkt")
	}

	err = expectWithOutput(runChild, "Enter text:")
	if err != nil {
		t.Fatalf("Waited for the prompt but not found: %v", err)
	}

	// Check the ppid file is really created
	cmd := fmt.Sprintf(`%s list --full|grep running`, ctx.cmd())
	output, err := exec.Command("/bin/sh", "-c", cmd).CombinedOutput()
	if err != nil {
		t.Fatalf("Couldn't list the pods: %v", err)
	}
	UUID := strings.Split(string(output), "\t")[0]

	pidFileName := filepath.Join(ctx.dataDir(), "pods/run", UUID, "ppid")
	if _, err := os.Stat(pidFileName); err != nil {
		t.Fatalf("Pid file missing: %v", err)
	}

	// Temporarily move the ppid file away
	pidFileNameBackup := pidFileName + ".backup"
	if err := os.Rename(pidFileName, pidFileNameBackup); err != nil {
		t.Fatalf("Cannot move ppid file away: %v", err)
	}

	// Start the "enter" command without the pidfile
	enterCmd := fmt.Sprintf("%s --debug enter %s /inspect --print-msg=RktEnterWorksFine", ctx.cmd(), UUID)
	t.Logf("%s", enterCmd)
	enterChild, err := gexpect.Spawn(enterCmd)
	if err != nil {
		t.Fatalf("Cannot exec rkt enter")
	}
	// Enter should be able to wait until the ppid file appears
	time.Sleep(1 * time.Second)

	return runChild, enterChild, pidFileName, pidFileNameBackup
}
Example #10
0
func TestVolumes(t *testing.T) {
	readFileImage := patchTestACI("rkt-inspect-read-file.aci", "--exec=/inspect --read-file")
	defer os.Remove(readFileImage)
	writeFileImage := patchTestACI("rkt-inspect-write-file.aci", "--exec=/inspect --write-file --read-file")
	defer os.Remove(writeFileImage)
	volRwReadFileImage := patchTestACI("rkt-inspect-vol-rw-read-file.aci", "--exec=/inspect --read-file", "--mounts=dir1,path=/dir1,readOnly=false")
	defer os.Remove(volRwReadFileImage)
	volRwWriteFileImage := patchTestACI("rkt-inspect-vol-rw-write-file.aci", "--exec=/inspect --write-file --read-file", "--mounts=dir1,path=/dir1,readOnly=false")
	defer os.Remove(volRwWriteFileImage)
	volRoReadFileImage := patchTestACI("rkt-inspect-vol-ro-read-file.aci", "--exec=/inspect --read-file", "--mounts=dir1,path=/dir1,readOnly=true")
	defer os.Remove(volRoReadFileImage)
	volRoWriteFileImage := patchTestACI("rkt-inspect-vol-ro-write-file.aci", "--exec=/inspect --write-file --read-file", "--mounts=dir1,path=/dir1,readOnly=true")
	defer os.Remove(volRoWriteFileImage)
	ctx := newRktRunCtx()
	defer ctx.cleanup()

	tmpdir, err := ioutil.TempDir("", "rkt-tests.")
	if err != nil {
		t.Fatalf("Cannot create temporary directory: %v", err)
	}
	defer os.RemoveAll(tmpdir)

	tmpfile := filepath.Join(tmpdir, "file")
	err = ioutil.WriteFile(tmpfile, []byte("host"), 0600)
	if err != nil {
		t.Fatalf("Cannot create temporary file: %v", err)
	}

	for i, tt := range volTests {
		cmd := strings.Replace(tt.rktCmd, "^TMPDIR^", tmpdir, -1)
		cmd = strings.Replace(cmd, "^RKT_BIN^", ctx.cmd(), -1)
		cmd = strings.Replace(cmd, "^READ_FILE^", readFileImage, -1)
		cmd = strings.Replace(cmd, "^WRITE_FILE^", writeFileImage, -1)
		cmd = strings.Replace(cmd, "^VOL_RO_READ_FILE^", volRoReadFileImage, -1)
		cmd = strings.Replace(cmd, "^VOL_RO_WRITE_FILE^", volRoWriteFileImage, -1)
		cmd = strings.Replace(cmd, "^VOL_RW_READ_FILE^", volRwReadFileImage, -1)
		cmd = strings.Replace(cmd, "^VOL_RW_WRITE_FILE^", volRwWriteFileImage, -1)

		t.Logf("Running test #%v: %v", i, cmd)

		child, err := gexpect.Spawn(cmd)
		if err != nil {
			t.Fatalf("Cannot exec rkt #%v: %v", i, err)
		}

		err = expectWithOutput(child, tt.expect)
		if err != nil {
			fmt.Printf("Command: %s\n", cmd)
			t.Fatalf("Expected %q but not found #%v: %v", tt.expect, i, err)
		}

		err = child.Wait()
		if err != nil {
			t.Fatalf("rkt didn't terminate correctly: %v", err)
		}
	}
}
Example #11
0
func main() {
	log.Printf("Testing Ping interact... \n")

	child, err := gexpect.Spawn("ping -c8 127.0.0.1")
	if err != nil {
		panic(err)
	}
	child.Interact()
	log.Printf("Success\n")
}
Example #12
0
// expectedRunRkt tries to fetch and run a prog.aci from host within
// given directory on host. Note that directory can be anything - it's
// useful for ensuring that image name is unique and for descriptive
// purposes.
func expectedRunRkt(ctx *rktRunCtx, t *testing.T, host, dir, line string) {
	cmd := fmt.Sprintf(`%s --debug --insecure-skip-verify run --mds-register=false %s/%s/prog.aci`, ctx.cmd(), host, dir)
	t.Logf("Running rkt: %s", cmd)
	child, err := gexpect.Spawn(cmd)
	if err != nil {
		t.Fatalf("Failed to run rkt: %v", err)
	}
	defer child.Wait()
	if err := expectWithOutput(child, line); err != nil {
		t.Fatalf("Didn't receive expected output %q: %v", line, err)
	}
}
Example #13
0
func TestCaps(t *testing.T) {
	ctx := newRktRunCtx()
	defer ctx.cleanup()

	for i, tt := range capsTests {
		var stage1FileName = "rkt-inspect-print-caps-stage1.aci"
		var stage2FileName = "rkt-inspect-print-caps-stage2.aci"
		stage1Args := []string{"--exec=/inspect --print-caps-pid=1 --print-user"}
		stage2Args := []string{"--exec=/inspect --print-caps-pid=0 --print-user"}
		if tt.capIsolator != "" {
			stage1Args = append(stage1Args, "--capability="+tt.capIsolator)
			stage2Args = append(stage2Args, "--capability="+tt.capIsolator)
		}
		patchTestACI(stage1FileName, stage1Args...)
		patchTestACI(stage2FileName, stage2Args...)
		defer os.Remove(stage1FileName)
		defer os.Remove(stage2FileName)

		for _, stage := range []int{1, 2} {
			t.Logf("Running test #%v: %v [stage %v]", i, tt.testName, stage)

			cmd := fmt.Sprintf("%s --debug --insecure-skip-verify run --set-env=CAPABILITY=%d ./rkt-inspect-print-caps-stage%d.aci", ctx.cmd(), int(tt.capa), stage)
			t.Logf("Command: %v", cmd)
			child, err := gexpect.Spawn(cmd)
			if err != nil {
				t.Fatalf("Cannot exec rkt #%v: %v", i, err)
			}

			expectedLine := tt.capa.String()
			if (stage == 1 && tt.capInStage1Expected) || (stage == 2 && tt.capInStage2Expected) {
				expectedLine += "=enabled"
			} else {
				expectedLine += "=disabled"
			}
			err = expectWithOutput(child, expectedLine)
			if err != nil {
				t.Fatalf("Expected %q but not found: %v", expectedLine, err)
			}

			err = expectWithOutput(child, "User: uid=0 euid=0 gid=0 egid=0")
			if err != nil {
				t.Fatalf("Expected user 0 but not found: %v", err)
			}

			err = child.Wait()
			if err != nil {
				t.Fatalf("rkt didn't terminate correctly: %v", err)
			}
		}
		ctx.reset()
	}
}
Example #14
0
func main() {
	waitChan := make(chan string)

	fmt.Printf("Starting screen.. \n")

	child, err := gexpect.Spawn("screen")
	if err != nil {
		panic(err)
	}

	sender, reciever := child.AsyncInteractChannels()
	go func() {
		waitString := ""
		count := 0
		for {
			select {
			case waitString = <-waitChan:
				count++
			case msg, open := <-reciever:
				if !open {
					return
				}
				fmt.Printf("Recieved: %s\n", msg)

				if strings.Contains(msg, waitString) {
					if count >= 1 {
						waitChan <- msg
						count -= 1
					}
				}
			}
		}
	}()
	wait := func(str string) {
		waitChan <- str
		<-waitChan
	}
	fmt.Printf("Waiting until started.. \n")
	wait(" ")
	fmt.Printf("Sending Enter.. \n")
	sender <- "\n"
	wait("$")
	fmt.Printf("Sending echo.. \n")
	sender <- "echo Hello World\n"
	wait("Hello World")
	fmt.Printf("Received echo. \n")
}
Example #15
0
func main() {
	fmt.Printf("Starting python.. \n")
	child, err := gexpect.Spawn("python")
	if err != nil {
		panic(err)
	}
	fmt.Printf("Expecting >>>.. \n")
	child.Expect(">>>")
	fmt.Printf("print 'Hello World'..\n")
	child.SendLine("print 'Hello World'")
	child.Expect(">>>")

	fmt.Printf("Interacting.. \n")
	child.Interact()
	fmt.Printf("Done \n")
	child.Close()
}
Example #16
0
func getImageId(ctx *rktRunCtx, name string) (string, error) {
	cmd := fmt.Sprintf(`/bin/sh -c "%s image list --fields=key,appname --no-legend | grep %s | awk '{print $1}'"`, ctx.cmd(), name)
	child, err := gexpect.Spawn(cmd)
	if err != nil {
		return "", fmt.Errorf("Cannot exec rkt: %v", err)
	}
	imageID, err := child.ReadLine()
	imageID = strings.TrimSpace(imageID)
	imageID = string(bytes.Trim([]byte(imageID), "\x00"))
	if err != nil {
		return "", fmt.Errorf("Cannot exec: %v", err)
	}
	if err := child.Wait(); err != nil {
		return "", fmt.Errorf("rkt didn't terminate correctly: %v", err)
	}
	return imageID, nil
}
Example #17
0
func TestNonRootCaps(t *testing.T) {
	ctx := newRktRunCtx()
	defer ctx.cleanup()

	for i, tt := range capsTests {
		var fileName = "rkt-inspect-print-caps-nonroot.aci"
		var args []string
		args = []string{"--exec=/inspect --print-caps-pid=0 --print-user", "--user=9000", "--group=9000"}
		if tt.capIsolator != "" {
			args = append(args, "--capability="+tt.capIsolator)
		}
		patchTestACI(fileName, args...)
		defer os.Remove(fileName)

		t.Logf("Running test #%v: %v [non-root]", i, tt.testName)

		cmd := fmt.Sprintf("%s --debug --insecure-skip-verify run --set-env=CAPABILITY=%d ./%s", ctx.cmd(), int(tt.capa), fileName)
		t.Logf("Command: %v", cmd)
		child, err := gexpect.Spawn(cmd)
		if err != nil {
			t.Fatalf("Cannot exec rkt #%v: %v", i, err)
		}

		expectedLine := tt.capa.String()
		if tt.nonrootCapExpected {
			expectedLine += "=enabled"
		} else {
			expectedLine += "=disabled"
		}
		err = expectWithOutput(child, expectedLine)
		if err != nil {
			t.Fatalf("Expected %q but not found: %v", expectedLine, err)
		}

		err = expectWithOutput(child, "User: uid=9000 euid=9000 gid=9000 egid=9000")
		if err != nil {
			t.Fatalf("Expected user 9000 but not found: %v", err)
		}

		err = child.Wait()
		if err != nil {
			t.Fatalf("rkt didn't terminate correctly: %v", err)
		}
		ctx.reset()
	}
}
Example #18
0
/*
 * No private net
 * ---
 * Container launches http server which must be reachable by the host via the
 * localhost address
 */
func TestPrivateNetOmittedConnectivity(t *testing.T) {
	httpServeAddr := "0.0.0.0:54321"
	httpGetAddr := "http://127.0.0.1:54321"

	testImageArgs := []string{"--exec=/inspect --serve-http=" + 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 --mds-register=false %s", ctx.cmd(), testImage)
	t.Logf("Command: %v", cmd)
	child, err := gexpect.Spawn(cmd)
	if err != nil {
		t.Fatalf("Cannot exec rkt: %v", err)
	}

	// Child opens the server
	c := make(chan struct{})
	go func() {
		err = child.Wait()
		if err != nil {
			t.Fatalf("rkt didn't terminate correctly: %v", err)
		}
		c <- struct{}{}
	}()

	// Host connects to the child
	go func() {
		expectedRegex := `serving on`
		result, _ := child.ExpectRegexFind(expectedRegex)
		if len(result) == 0 {
			t.Fatalf("Expected %q but not found", expectedRegex)
		}
		body, err := test_netutils.HttpGet(httpGetAddr)
		if err != nil {
			log.Fatalf("%v\n", err)
		}
		log.Printf("HTTP-Get received: %s", body)
	}()

	<-c
}
Example #19
0
func removeImageId(ctx *rktRunCtx, imageID string, shouldWork bool) error {
	expect := fmt.Sprintf(rmImageReferenced, imageID)
	if shouldWork {
		expect = rmImageOk
	}
	cmd := fmt.Sprintf("%s image rm %s", ctx.cmd(), imageID)
	child, err := gexpect.Spawn(cmd)
	if err != nil {
		return fmt.Errorf("Cannot exec: %v", err)
	}
	if err := expectWithOutput(child, expect); err != nil {
		return fmt.Errorf("Expected %q but not found: %v", expect, err)
	}
	if err := child.Wait(); err != nil {
		return fmt.Errorf("rkt didn't terminate correctly: %v", err)
	}
	return nil
}
Example #20
0
func TestInteractive(t *testing.T) {
	ctx := newRktRunCtx()
	defer ctx.cleanup()

	for i, tt := range interactiveTests {
		t.Logf("Running test #%v: %v", i, tt.testName)

		aciFileName := "rkt-inspect-interactive.aci"
		patchTestACI(aciFileName, tt.aciBuildArgs...)
		defer os.Remove(aciFileName)

		rktCmd := fmt.Sprintf("%s %s", ctx.cmd(), tt.rktArgs)
		t.Logf("Command: %v", rktCmd)
		child, err := gexpect.Spawn(rktCmd)
		if err != nil {
			t.Fatalf("Cannot exec rkt #%v: %v", i, err)
		}
		if tt.say != "" {
			err = expectTimeoutWithOutput(child, "Enter text:", time.Minute)
			if err != nil {
				t.Fatalf("Waited for the prompt but not found #%v: %v", i, err)
			}

			err = child.SendLine(tt.say)
			if err != nil {
				t.Fatalf("Failed to send %q on the prompt #%v: %v", tt.say, i, err)
			}
		}

		err = expectTimeoutWithOutput(child, tt.expect, time.Minute)
		if err != nil {
			t.Fatalf("Expected %q but not found #%v: %v", tt.expect, i, err)
		}

		err = child.Wait()
		if err != nil {
			t.Fatalf("rkt didn't terminate correctly: %v", err)
		}
	}
}
Example #21
0
func main() {
	log.Printf("Testing Ftp... ")

	child, err := gexpect.Spawn("ftp ftp.openbsd.org")
	if err != nil {
		panic(err)
	}
	child.Expect("Name")
	child.SendLine("anonymous")
	child.Expect("Password")
	child.SendLine("*****@*****.**")
	child.Expect("ftp> ")
	child.SendLine("cd /pub/OpenBSD/3.7/packages/i386")
	child.Expect("ftp> ")
	child.SendLine("bin")
	child.Expect("ftp> ")
	child.SendLine("prompt")
	child.Expect("ftp> ")
	child.SendLine("pwd")
	child.Expect("ftp> ")
	log.Printf("Success\n")
}
Example #22
0
/*
 * Default private-net
 * ---
 * Container must be in a separate network namespace with private-net
 */
func TestPrivateNetDefaultNetNS(t *testing.T) {
	testImageArgs := []string{"--exec=/inspect --print-netns"}
	testImage := patchTestACI("rkt-inspect-networking.aci", testImageArgs...)
	defer os.Remove(testImage)

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

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

	expectedRegex := `NetNS: (net:\[\d+\])`
	result, _ := child.ExpectRegexFind(expectedRegex)
	if len(result) == 0 {
		t.Fatalf("Expected %q but not found", expectedRegex)
	}

	ns, err := os.Readlink("/proc/self/ns/net")
	if err != nil {
		t.Fatalf("Cannot evaluate NetNS symlink: %v", err)
	}

	if nsChanged := ns != result[1]; !nsChanged {
		t.Fatalf("container did not leave host netns")
	}

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

	ctx.reset()
}
Example #23
0
func TestFailure(t *testing.T) {
	patchTestACI("rkt-inspect-exit20.aci", "--exec=/inspect --print-msg=Hello --exit-code=20")
	defer os.Remove("rkt-inspect-exit20.aci")
	ctx := newRktRunCtx()
	defer ctx.cleanup()

	child, err := gexpect.Spawn(fmt.Sprintf("%s --debug --insecure-skip-verify run ./rkt-inspect-exit20.aci", ctx.cmd()))
	if err != nil {
		t.Fatalf("Cannot exec rkt")
	}
	err = child.Expect("Hello")
	if err != nil {
		t.Fatalf("Missing hello")
	}
	err = child.Expect("main process exited, code=exited, status=20")
	if err != nil {
		t.Fatalf("Missing hello")
	}

	err = child.Wait()
	if err != nil {
		t.Fatalf("rkt didn't terminate correctly: %v", err)
	}
}
// Test running pod manifests that contains just one app.
// TODO(yifan): Add more tests for port mappings. and multiple apps.
func TestPodManifest(t *testing.T) {
	ctx := newRktRunCtx()
	defer ctx.cleanup()

	tmpdir, err := ioutil.TempDir("", "rkt-tests.")
	if err != nil {
		t.Fatalf("Cannot create temporary directory: %v", err)
	}
	defer os.RemoveAll(tmpdir)

	boolFalse, boolTrue := false, true

	tests := []struct {
		imageName      string
		imagePatches   []string
		podManifest    *schema.PodManifest
		shouldSuccess  bool
		expectedResult string
	}{
		{
			// Simple read.
			"rkt-test-run-pod-manifest-read.aci",
			[]string{},
			&schema.PodManifest{
				Apps: []schema.RuntimeApp{
					{
						Name: baseAppName,
						App: &types.App{
							Exec:  []string{"/inspect", "--read-file"},
							User:  "******",
							Group: "0",
							Environment: []types.EnvironmentVariable{
								{"FILE", "/dir1/file"},
							},
						},
					},
				},
			},
			true,
			"dir1",
		},
		{
			// Simple read after write with volume mounted.
			"rkt-test-run-pod-manifest-vol-rw.aci",
			[]string{},
			&schema.PodManifest{
				Apps: []schema.RuntimeApp{
					{
						Name: baseAppName,
						App: &types.App{
							Exec:  []string{"/inspect", "--write-file", "--read-file"},
							User:  "******",
							Group: "0",
							Environment: []types.EnvironmentVariable{
								{"FILE", "/dir1/file"},
								{"CONTENT", "host:foo"},
							},
							MountPoints: []types.MountPoint{
								{"dir1", "/dir1", false},
							},
						},
					},
				},
				Volumes: []types.Volume{
					{"dir1", "host", tmpdir, nil},
				},
			},
			true,
			"host:foo",
		},
		{
			// Simple read after write with read-only mount point, should fail.
			"rkt-test-run-pod-manifest-vol-ro.aci",
			[]string{},
			&schema.PodManifest{
				Apps: []schema.RuntimeApp{
					{
						Name: baseAppName,
						App: &types.App{
							Exec:  []string{"/inspect", "--write-file", "--read-file"},
							User:  "******",
							Group: "0",
							Environment: []types.EnvironmentVariable{
								{"FILE", "/dir1/file"},
								{"CONTENT", "bar"},
							},
							MountPoints: []types.MountPoint{
								{"dir1", "/dir1", true},
							},
						},
					},
				},
				Volumes: []types.Volume{
					{"dir1", "host", tmpdir, nil},
				},
			},
			false,
			`Cannot write to file "/dir1/file": open /dir1/file: read-only file system`,
		},
		{
			// Simple read after write with volume mounted.
			// Override the image's mount point spec. This should fail as the volume is
			// read-only in pod manifest, (which will override the mount point in both image/pod manifest).
			"rkt-test-run-pod-manifest-vol-rw-override.aci",
			[]string{
				"--mounts=dir1,path=/dir1,readOnly=false",
			},
			&schema.PodManifest{
				Apps: []schema.RuntimeApp{
					{
						Name: baseAppName,
						App: &types.App{
							Exec:  []string{"/inspect", "--write-file", "--read-file"},
							User:  "******",
							Group: "0",
							Environment: []types.EnvironmentVariable{
								{"FILE", "/dir1/file"},
								{"CONTENT", "bar"},
							},
							MountPoints: []types.MountPoint{
								{"dir1", "/dir1", false},
							},
						},
					},
				},
				Volumes: []types.Volume{
					{"dir1", "host", tmpdir, &boolTrue},
				},
			},
			false,
			`Cannot write to file "/dir1/file": open /dir1/file: read-only file system`,
		},
		{
			// Simple read after write with volume mounted.
			// Override the image's mount point spec.
			"rkt-test-run-pod-manifest-vol-rw-override.aci",
			[]string{
				"--mounts=dir1,path=/dir1,readOnly=true",
			},
			&schema.PodManifest{
				Apps: []schema.RuntimeApp{
					{
						Name: baseAppName,
						App: &types.App{
							Exec:  []string{"/inspect", "--write-file", "--read-file"},
							User:  "******",
							Group: "0",
							Environment: []types.EnvironmentVariable{
								{"FILE", "/dir2/file"},
								{"CONTENT", "host:bar"},
							},
							MountPoints: []types.MountPoint{
								{"dir1", "/dir2", false},
							},
						},
					},
				},
				Volumes: []types.Volume{
					{"dir1", "host", tmpdir, nil},
				},
			},
			true,
			"host:bar",
		},
		{
			// Simple read after write with volume mounted, no apps in pod manifest.
			"rkt-test-run-pod-manifest-vol-rw-no-app.aci",
			[]string{
				"--exec=/inspect --write-file --read-file --file-name=/dir1/file --content=host:baz",
				"--mounts=dir1,path=/dir1,readOnly=false",
			},
			&schema.PodManifest{
				Apps: []schema.RuntimeApp{
					{Name: baseAppName},
				},
				Volumes: []types.Volume{
					{"dir1", "host", tmpdir, nil},
				},
			},
			true,
			"host:baz",
		},
		{
			// Simple read after write with volume mounted, no apps in pod manifest.
			// This should succeed even the mount point in image manifest is readOnly,
			// because it is overrided by the volume's readOnly.
			"rkt-test-run-pod-manifest-vol-ro-no-app.aci",
			[]string{
				"--exec=/inspect --write-file --read-file --file-name=/dir1/file --content=host:zaz",
				"--mounts=dir1,path=/dir1,readOnly=true",
			},
			&schema.PodManifest{
				Apps: []schema.RuntimeApp{
					{Name: baseAppName},
				},
				Volumes: []types.Volume{
					{"dir1", "host", tmpdir, &boolFalse},
				},
			},
			true,
			"host:zaz",
		},
		{
			// Simple read after write with read-only volume mounted, no apps in pod manifest.
			// This should fail as the volume is read-only.
			"rkt-test-run-pod-manifest-vol-ro-no-app.aci",
			[]string{
				"--exec=/inspect --write-file --read-file --file-name=/dir1/file --content=baz",
				"--mounts=dir1,path=/dir1,readOnly=false",
			},
			&schema.PodManifest{
				Apps: []schema.RuntimeApp{
					{Name: baseAppName},
				},
				Volumes: []types.Volume{
					{"dir1", "host", tmpdir, &boolTrue},
				},
			},
			false,
			`Cannot write to file "/dir1/file": open /dir1/file: read-only file system`,
		},
	}

	for i, tt := range tests {
		patchTestACI(tt.imageName, tt.imagePatches...)
		hash := importImageAndFetchHash(t, ctx, tt.imageName)
		defer os.Remove(tt.imageName)

		tt.podManifest.ACKind = schema.PodManifestKind
		tt.podManifest.ACVersion = schema.AppContainerVersion

		imgName := types.MustACIdentifier(tt.imageName)
		imgID, err := types.NewHash(hash)
		if err != nil {
			t.Fatalf("Cannot generate types.Hash from %v: %v", hash, err)
		}

		for i := range tt.podManifest.Apps {
			ra := &tt.podManifest.Apps[i]
			ra.Image.Name = imgName
			ra.Image.ID = *imgID
		}
		manifestFile := generatePodManifestFile(t, tt.podManifest)
		defer os.Remove(manifestFile)

		// 1. Test 'rkt run'.
		runCmd := fmt.Sprintf("%s run --pod-manifest=%s", ctx.cmd(), manifestFile)
		t.Logf("Running 'run' test #%v: %v", i, runCmd)
		child, err := gexpect.Spawn(runCmd)
		if err != nil {
			t.Fatalf("Cannot exec rkt #%v: %v", i, err)
		}

		if tt.expectedResult != "" {
			if err := child.Expect(tt.expectedResult); err != nil {
				t.Fatalf("Expected %q but not found: %v", tt.expectedResult, err)
			}
		}
		if err := child.Wait(); err != nil {
			if tt.shouldSuccess {
				t.Fatalf("rkt didn't terminate correctly: %v", err)
			}
		}
		verifyHostFile(t, tmpdir, "file", i, tt.expectedResult)

		// 2. Test 'rkt prepare' + 'rkt run-prepared'.
		cmds := strings.Fields(ctx.cmd())
		prepareCmd := exec.Command(cmds[0], cmds[1:]...)
		prepareArg := fmt.Sprintf("--pod-manifest=%s", manifestFile)
		prepareCmd.Args = append(prepareCmd.Args, "--insecure-skip-verify", "prepare", prepareArg)
		output, err := prepareCmd.Output()
		if err != nil {
			t.Fatalf("Cannot read the output: %v", err)
		}

		podIDStr := strings.TrimSpace(string(output))
		podID, err := types.NewUUID(podIDStr)
		if err != nil {
			t.Fatalf("%q is not a valid UUID: %v", podIDStr, err)
		}

		runPreparedCmd := fmt.Sprintf("%s run-prepared %s", ctx.cmd(), podID.String())
		t.Logf("Running 'run' test #%v: %v", i, runPreparedCmd)
		child, err = gexpect.Spawn(runPreparedCmd)
		if err != nil {
			t.Fatalf("Cannot exec rkt #%v: %v", i, err)
		}

		if tt.expectedResult != "" {
			if err := child.Expect(tt.expectedResult); err != nil {
				t.Fatalf("Expected %q but not found: %v", tt.expectedResult, err)
			}
		}
		if err := child.Wait(); err != nil {
			if tt.shouldSuccess {
				t.Fatalf("rkt didn't terminate correctly: %v", err)
			}
		}
		verifyHostFile(t, tmpdir, "file", i, tt.expectedResult)
	}
}
Example #25
0
func TestImageRm(t *testing.T) {
	patchTestACI(unreferencedACI, fmt.Sprintf("--name=%s", unreferencedApp))
	defer os.Remove(unreferencedACI)
	ctx := newRktRunCtx()
	defer ctx.cleanup()

	cmd := fmt.Sprintf("%s --insecure-skip-verify fetch %s", ctx.cmd(), unreferencedACI)
	t.Logf("Fetching %s: %v", unreferencedACI, cmd)
	child, err := gexpect.Spawn(cmd)
	if err != nil {
		t.Fatalf("Cannot exec: %v", err)
	}
	if err := child.Wait(); err != nil {
		t.Fatalf("rkt didn't terminate correctly: %v", err)
	}

	cmd = fmt.Sprintf("%s --insecure-skip-verify run %s", ctx.cmd(), referencedACI)
	t.Logf("Running %s: %v", referencedACI, cmd)
	child, err = gexpect.Spawn(cmd)
	if err != nil {
		t.Fatalf("Cannot exec: %v", err)
	}
	if err := child.Wait(); err != nil {
		t.Fatalf("rkt didn't terminate correctly: %v", err)
	}

	t.Logf("Retrieving stage1 imageID")
	stage1ImageID, err := getImageId(ctx, stage1App)
	if err != nil {
		t.Fatalf("rkt didn't terminate correctly: %v", err)
	}

	t.Logf("Retrieving %s imageID", referencedApp)
	referencedImageID, err := getImageId(ctx, referencedApp)
	if err != nil {
		t.Fatalf("rkt didn't terminate correctly: %v", err)
	}

	t.Logf("Retrieving %s imageID", unreferencedApp)
	unreferencedImageID, err := getImageId(ctx, unreferencedApp)
	if err != nil {
		t.Fatalf("rkt didn't terminate correctly: %v", err)
	}

	t.Logf("Removing stage1 image (should fail as referenced)")
	if err := removeImageId(ctx, stage1ImageID, false); err != nil {
		t.Fatalf("unexpected error: %v", err)
	}

	t.Logf("Removing image for app %s (should fail as referenced)", referencedApp)
	if err := removeImageId(ctx, referencedImageID, false); err != nil {
		t.Fatalf("unexpected error: %v", err)
	}

	t.Logf("Removing image for app %s (should work)", unreferencedApp)
	if err := removeImageId(ctx, unreferencedImageID, true); err != nil {
		t.Fatalf("unexpected error: %v", err)
	}

	cmd = fmt.Sprintf("%s gc --grace-period=0s", ctx.cmd())
	t.Logf("Running gc: %v", cmd)
	child, err = gexpect.Spawn(cmd)
	if err != nil {
		t.Fatalf("Cannot exec: %v", err)
	}
	if err := child.Wait(); err != nil {
		t.Fatalf("rkt didn't terminate correctly: %v", err)
	}

	t.Logf("Removing stage1 image (should work)")
	if err := removeImageId(ctx, stage1ImageID, true); err != nil {
		t.Fatalf("unexpected error: %v", err)
	}

	t.Logf("Removing image for app %s (should work)", referencedApp)
	if err := removeImageId(ctx, referencedImageID, true); err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
}
Example #26
0
// TestImageExport tests 'rkt image export', it will import some existing
// image, export it with rkt image export and check that the exported ACI hash
// matches the hash of the imported ACI
func TestImageExport(t *testing.T) {
	testImage := "rkt-inspect-image-export.aci"
	testImageName := "coreos.com/rkt-image-export-test"
	expectManifest := strings.Replace(manifestExportTemplate, "IMG_NAME", testImageName, -1)

	tmpDir, err := ioutil.TempDir("", "rkt-TestImageExport-")
	if err != nil {
		panic(fmt.Sprintf("Cannot create temp dir: %v", err))
	}
	defer os.RemoveAll(tmpDir)

	tmpManifest, err := ioutil.TempFile(tmpDir, "manifest")
	if err != nil {
		panic(fmt.Sprintf("Cannot create temp manifest: %v", err))
	}
	defer tmpManifest.Close()
	tmpManifestName := tmpManifest.Name()
	if err := ioutil.WriteFile(tmpManifestName, []byte(expectManifest), 0600); err != nil {
		panic(fmt.Sprintf("Cannot write to temp manifest: %v", err))
	}
	defer os.Remove(tmpManifestName)

	patchTestACI(testImage, "--manifest", tmpManifestName)
	defer os.Remove(testImage)
	ctx := newRktRunCtx()
	defer ctx.cleanup()

	testImageKey := importImageAndFetchHash(t, ctx, testImage)

	testImageHash, err := getHash(testImage)
	if err != nil {
		panic(fmt.Sprintf("Error getting image hash: %v", err))
	}

	tests := []struct {
		image        string
		shouldFind   bool
		expectedHash string
	}{
		{
			testImageName,
			true,
			testImageHash,
		},
		{
			testImageKey,
			true,
			testImageHash,
		},
		{
			"sha512-not-existed",
			false,
			"",
		},
		{
			"some~random~aci~name",
			false,
			"",
		},
	}

	for i, tt := range tests {
		outputAciPath := filepath.Join(tmpDir, fmt.Sprintf("exported-%d.aci", i))
		runCmd := fmt.Sprintf("%s image export %s %s", ctx.cmd(), tt.image, outputAciPath)
		t.Logf("Running 'image export' test #%v: %v", i, runCmd)
		child, err := gexpect.Spawn(runCmd)
		if err != nil {
			t.Fatalf("Cannot exec rkt #%v: %v", i, err)
		}

		if err := child.Wait(); err != nil {
			if !tt.shouldFind && err.Error() == "exit status 1" {
				continue
			} else if tt.shouldFind || err.Error() != "exit status 1" {
				t.Fatalf("rkt didn't terminate correctly: %v", err)
			}
		}

		exportedHash, err := getHash(outputAciPath)
		if err != nil {
			t.Fatalf("Error getting exported image hash: %v", err)
		}

		if exportedHash != tt.expectedHash {
			t.Fatalf("Expected hash %q but got %s", tt.expectedHash, exportedHash)
		}
	}
}
Example #27
0
// TestRunPrepareFromFile tests that when 'rkt run/prepare' a local ACI, it will bypass the
// on-disk store.
func TestRunPrepareFromFile(t *testing.T) {
	foundMsg := "found image in local store"
	image := "rkt-inspect-implicit-fetch.aci"

	imagePath := patchTestACI(image, "--exec=/inspect")
	defer os.Remove(imagePath)

	tests := []string{
		imagePath,
		"file://" + imagePath,
	}

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

	importImageAndFetchHash(t, ctx, imagePath)

	for _, tt := range tests {

		// 1. Try run/prepare with '--local', should not get the $foundMsg, since we will ignore the '--local' when
		// the image is a filepath.
		cmds := []string{
			fmt.Sprintf("%s --insecure-skip-verify run --mds-register=false --local %s", ctx.cmd(), tt),
			fmt.Sprintf("%s --insecure-skip-verify prepare --local %s", ctx.cmd(), tt),
		}

		for _, cmd := range cmds {
			t.Logf("Running test %v", cmd)

			child, err := gexpect.Spawn(cmd)
			if err != nil {
				t.Fatalf("Cannot exec rkt: %v", err)
			}

			if err := child.Expect(foundMsg); err == nil {
				t.Fatalf("%q should not be found", foundMsg)
			}

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

		// 2. Try run/prepare without '--local', should not get $foundMsg either.
		cmds = []string{
			fmt.Sprintf("%s --insecure-skip-verify run --mds-register=false %s", ctx.cmd(), tt),
			fmt.Sprintf("%s --insecure-skip-verify prepare %s", ctx.cmd(), tt),
		}

		for _, cmd := range cmds {
			t.Logf("Running test %v", cmd)

			child, err := gexpect.Spawn(cmd)
			if err != nil {
				t.Fatalf("Cannot exec rkt: %v", err)
			}
			if err := child.Expect(foundMsg); err == nil {
				t.Fatalf("%q should not be found", foundMsg)
			}
			if err := child.Wait(); err != nil {
				t.Fatalf("rkt didn't terminate correctly: %v", err)
			}
		}
	}
}
// TestCatManifest tests 'rkt image cat-manifest', it will:
// Read some existing image manifest via the image name, and verify the result.
// Read some existing image manifest via the image hash, and verify the result.
// Read some non-existing image manifest via the image name, and verify nothing is found.
// Read some non-existing image manifest via the image hash, and verify nothing is found.
func TestCatManifest(t *testing.T) {
	testImage := "rkt-inspect-image-cat-manifest.aci"
	testImageName := "coreos.com/rkt-cat-manifest-test"
	expectManifest := strings.Replace(manifestTemplate, "IMG_NAME", testImageName, -1)

	tmpManifest, err := ioutil.TempFile("", "rkt-TestCatManifest-")
	if err != nil {
		t.Fatalf("Cannot create temp manifest: %v", err)
	}
	if err := ioutil.WriteFile(tmpManifest.Name(), []byte(expectManifest), 0600); err != nil {
		t.Fatalf("Cannot write to temp manifest: %v", err)
	}
	defer os.Remove(tmpManifest.Name())

	patchTestACI(testImage, "--manifest", tmpManifest.Name())
	defer os.Remove(testImage)
	ctx := newRktRunCtx()
	defer ctx.cleanup()

	testImageHash := importImageAndFetchHash(t, ctx, testImage)

	tests := []struct {
		image      string
		shouldFind bool
		expect     string
	}{
		{
			testImageName,
			true,
			expectManifest,
		},
		{
			testImageHash,
			true,
			expectManifest,
		},
		{
			"sha512-not-existed",
			false,
			"",
		},
		{
			"some~random~aci~name",
			false,
			"",
		},
	}

	for i, tt := range tests {
		runCmd := fmt.Sprintf("%s image cat-manifest %s", ctx.cmd(), tt.image)
		t.Logf("Running 'run' test #%v: %v", i, runCmd)
		child, err := gexpect.Spawn(runCmd)
		if err != nil {
			t.Fatalf("Cannot exec rkt #%v: %v", i, err)
		}

		if tt.expect != "" {
			if err := expectWithOutput(child, tt.expect); err != nil {
				t.Fatalf("Expected %q but not found: %v", tt.expect, err)
			}
		}
		if err := child.Wait(); err != nil {
			if tt.shouldFind || err.Error() != "exit status 1" {
				t.Fatalf("rkt didn't terminate correctly: %v", err)
			}
		}
	}
}
Example #29
0
// TestImageRender tests 'rkt image render', it will import some existing empty
// image with a dependency on an image with the inspect binary, render it with
// rkt image render and check that the exported image has the /inspect file and
// that its hash matches the original inspect binary hash
func TestImageRender(t *testing.T) {
	baseImage := os.Getenv("RKT_INSPECT_IMAGE")
	if baseImage == "" {
		panic("Empty RKT_INSPECT_IMAGE environment variable")
	}
	emptyImage := os.Getenv("RKT_EMPTY_IMAGE")
	if emptyImage == "" {
		panic("Empty RKT_INSPECT_IMAGE environment variable")
	}
	testImageName := "coreos.com/rkt-image-render-test"
	inspectFile := os.Getenv("INSPECT_BINARY")
	if inspectFile == "" {
		panic("Empty INSPECT_BINARY environment variable")
	}
	inspectHash, err := getHash(inspectFile)
	if err != nil {
		panic("Cannot get inspect binary's hash")
	}

	expectManifest := strings.Replace(manifestRenderTemplate, "IMG_NAME", testImageName, -1)

	tmpDir, err := ioutil.TempDir("", "rkt-TestImageRender-")
	if err != nil {
		panic(fmt.Sprintf("Cannot create temp dir: %v", err))
	}
	defer os.RemoveAll(tmpDir)

	tmpManifest, err := ioutil.TempFile(tmpDir, "manifest")
	if err != nil {
		panic(fmt.Sprintf("Cannot create temp manifest: %v", err))
	}
	if err := ioutil.WriteFile(tmpManifest.Name(), []byte(expectManifest), 0600); err != nil {
		panic(fmt.Sprintf("Cannot write to temp manifest: %v", err))
	}
	defer os.Remove(tmpManifest.Name())

	testImage := patchACI(emptyImage, "rkt-inspect-image-render.aci", "--manifest", tmpManifest.Name())
	defer os.Remove(testImage)
	ctx := newRktRunCtx()
	defer ctx.cleanup()

	_ = importImageAndFetchHash(t, ctx, baseImage)
	testImageShortHash := importImageAndFetchHash(t, ctx, testImage)

	tests := []struct {
		image        string
		shouldFind   bool
		expectedHash string
	}{
		{
			testImageName,
			true,
			inspectHash,
		},
		{
			testImageShortHash,
			true,
			inspectHash,
		},
		{
			"sha512-not-existed",
			false,
			"",
		},
		{
			"some~random~aci~name",
			false,
			"",
		},
	}

	for i, tt := range tests {
		outputPath := filepath.Join(tmpDir, fmt.Sprintf("rendered-%d", i))
		runCmd := fmt.Sprintf("%s image render --rootfs-only %s %s", ctx.cmd(), tt.image, outputPath)
		t.Logf("Running 'image render' test #%v: %v", i, runCmd)
		child, err := gexpect.Spawn(runCmd)
		if err != nil {
			t.Fatalf("Cannot exec rkt #%v: %v", i, err)
		}

		if err := child.Wait(); err != nil {
			if !tt.shouldFind && err.Error() == "exit status 1" {
				continue
			} else if tt.shouldFind || err.Error() != "exit status 1" {
				t.Fatalf("rkt didn't terminate correctly: %v", err)
			}
		}

		renderedInspectHash, err := getHash(filepath.Join(outputPath, "inspect"))
		if err != nil {
			t.Fatalf("Cannot get rendered inspect binary's hash")
		}
		if renderedInspectHash != tt.expectedHash {
			t.Fatalf("Expected /inspect hash %q but got %s", tt.expectedHash, renderedInspectHash)
		}
	}
}
Example #30
0
func TestEnv(t *testing.T) {
	printVarFromManifestImage := patchTestACI("rkt-inspect-print-var-from-manifest.aci", "--exec=/inspect --print-env=VAR_FROM_MANIFEST")
	defer os.Remove(printVarFromManifestImage)
	printVarOtherImage := patchTestACI("rkt-inspect-print-var-other.aci", "--exec=/inspect --print-env=VAR_OTHER")
	defer os.Remove(printVarOtherImage)
	sleepImage := patchTestACI("rkt-inspect-sleep.aci", "--exec=/inspect --read-stdin")
	defer os.Remove(sleepImage)
	ctx := newRktRunCtx()
	defer ctx.cleanup()

	replacePlaceholders := func(cmd string) string {
		fixed := cmd
		fixed = strings.Replace(fixed, "^RKT_BIN^", ctx.cmd(), -1)
		fixed = strings.Replace(fixed, "^PRINT_VAR_FROM_MANIFEST^", printVarFromManifestImage, -1)
		fixed = strings.Replace(fixed, "^PRINT_VAR_OTHER^", printVarOtherImage, -1)
		fixed = strings.Replace(fixed, "^SLEEP^", sleepImage, -1)
		return fixed
	}
	for i, tt := range envTests {
		// 'run' tests
		runCmd := replacePlaceholders(tt.runCmd)
		t.Logf("Running 'run' test #%v: %v", i, runCmd)
		child, err := gexpect.Spawn(runCmd)
		if err != nil {
			t.Fatalf("Cannot exec rkt #%v: %v", i, err)
		}

		err = expectWithOutput(child, tt.runExpect)
		if err != nil {
			t.Fatalf("Expected %q but not found: %v", tt.runExpect, err)
		}

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

		// 'enter' tests
		sleepCmd := replacePlaceholders(tt.sleepCmd)
		t.Logf("Running 'enter' test #%v: sleep: %v", i, sleepCmd)
		child, err = gexpect.Spawn(sleepCmd)
		if err != nil {
			t.Fatalf("Cannot exec rkt #%v: %v", i, err)
		}

		err = expectWithOutput(child, "Enter text:")
		if err != nil {
			t.Fatalf("Waited for the prompt but not found #%v: %v", i, err)
		}

		enterCmd := replacePlaceholders(tt.enterCmd)
		t.Logf("Running 'enter' test #%v: enter: %v", i, enterCmd)
		enterChild, err := gexpect.Spawn(enterCmd)
		if err != nil {
			t.Fatalf("Cannot exec rkt #%v: %v", i, err)
		}

		err = expectWithOutput(enterChild, tt.runExpect)
		if err != nil {
			t.Fatalf("Expected %q but not found: %v", tt.runExpect, err)
		}

		err = enterChild.Wait()
		if err != nil {
			t.Fatalf("rkt didn't terminate correctly: %v", err)
		}
		err = child.SendLine("Bye")
		if err != nil {
			t.Fatalf("rkt couldn't write to the container: %v", err)
		}
		err = expectWithOutput(child, "Received text: Bye")
		if err != nil {
			t.Fatalf("Expected Bye but not found #%v: %v", i, err)
		}

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