// 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) { // First, check that --insecure-skip-verify is required // The server does not provide signatures for now. cmd := fmt.Sprintf(`%s --debug 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() signatureErrorLine := "error downloading the signature file" if err := expectWithOutput(child, signatureErrorLine); err != nil { t.Fatalf("Didn't receive expected output %q: %v", signatureErrorLine, err) } // Then, run with --insecure-skip-verify 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) } }
func testFetchFromFile(t *testing.T, arg string, image string) { fetchFromFileMsg := fmt.Sprintf("using image from file %s", image) ctx := newRktRunCtx() defer ctx.cleanup() cmd := fmt.Sprintf("%s %s %s", ctx.cmd(), arg, image) t.Logf("Running test %v", cmd) // 1. Run cmd, should get $fetchFromFileMsg. child, err := gexpect.Spawn(cmd) if err != nil { t.Fatalf("Cannot exec rkt: %v", err) } if err := expectWithOutput(child, fetchFromFileMsg); err != nil { t.Fatalf("%q should be found", fetchFromFileMsg) } child.Wait() // 1. Run cmd again, should get $fetchFromFileMsg. child, err = gexpect.Spawn(cmd) if err != nil { t.Fatalf("Cannot exec rkt: %v", err) } if err := expectWithOutput(child, fetchFromFileMsg); err != nil { t.Fatalf("%q should be found", fetchFromFileMsg) } if err := child.Wait(); err != nil { t.Fatalf("rkt didn't terminate correctly: %v", err) } }
// 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) } } }
/* * 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() }
/* * Host network * --- * Container must have the same network namespace as the host */ func TestNetHost(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 --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) } expectedRegex := `NetNS: (net:\[\d+\])` result, out, err := expectRegexWithOutput(child, expectedRegex) if err != nil { t.Fatalf("Error: %v\nOutput: %v", err, out) } 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 left host netns") } err = child.Wait() if err != nil { t.Fatalf("rkt didn't terminate correctly: %v", err) } }
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 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) } } }
func TestRunOverrideExec(t *testing.T) { execImage := patchTestACI("rkt-exec-override.aci", "--exec=/inspect") defer os.Remove(execImage) ctx := newRktRunCtx() defer ctx.cleanup() for i, tt := range []struct { rktCmd string expectedLine string }{ { // Sanity check - make sure no --exec override prints the expected exec invocation rktCmd: fmt.Sprintf("%s --insecure-skip-verify run --mds-register=false %s -- --print-exec", ctx.cmd(), execImage), expectedLine: "inspect execed as: /inspect", }, { // Now test overriding the entrypoint (which is a symlink to /inspect so should behave identically) rktCmd: fmt.Sprintf("%s --insecure-skip-verify run --mds-register=false %s --exec /inspect-link -- --print-exec", ctx.cmd(), execImage), expectedLine: "inspect execed as: /inspect-link", }, } { child, err := gexpect.Spawn(tt.rktCmd) if err != nil { t.Fatalf("%d: cannot exec rkt: %v", i, err) } if err = expectWithOutput(child, tt.expectedLine); err != nil { t.Fatalf("%d: didn't receive expected output %q: %v", i, tt.expectedLine, err) } if err = child.Wait(); err != nil { t.Fatalf("%d: rkt didn't terminate correctly: %v", i, err) } } }
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) } }
// 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/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:latest", ctx.cmd()), fmt.Sprintf("%s --insecure-skip-verify prepare docker://busybox", 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 := expectWithOutput(child, 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) } } }
func TestPrivateNetOverride(t *testing.T) { ctx := newRktRunCtx() defer ctx.cleanup() defer ctx.reset() 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: "overridemacvlan", Type: "macvlan", Master: iface.Name, Ipam: ipamTemplateT{ Type: "host-local", Subnet: "10.1.4.0/24", }, } netdir := prepareTestNet(t, ctx, nt) defer os.RemoveAll(netdir) testImageArgs := []string{"--exec=/inspect --print-ipv4=eth0"} testImage := patchTestACI("rkt-inspect-networking1.aci", testImageArgs...) defer os.Remove(testImage) expectedIP := "10.1.4.244" cmd := fmt.Sprintf("%s --debug --insecure-skip-verify run --private-net=all --private-net=\"%s:IP=%s\" --mds-register=false %s", ctx.cmd(), nt.Name, expectedIP, testImage) fmt.Printf("Command: %v\n", cmd) child, err := gexpect.Spawn(cmd) if err != nil { t.Fatalf("Cannot exec rkt: %v", err) return } defer func() { err = child.Wait() if err != nil { t.Fatalf("rkt didn't terminate correctly: %v", err) } }() expectedRegex := `IPv4: (\d+\.\d+\.\d+\.\d+)` result, out, err := expectRegexTimeoutWithOutput(child, expectedRegex, 30*time.Second) if err != nil { t.Fatalf("Error: %v\nOutput: %v", err, out) return } containerIP := result[1] if expectedIP != containerIP { t.Fatalf("overriding IP did not work: Got %q but expected %q", containerIP, expectedIP) } }
func (a *GoroutineAssistant) SpawnOrFail(cmd string) *gexpect.ExpectSubprocess { a.t.Logf("Command: %v", cmd) child, err := gexpect.Spawn(cmd) if err != nil { a.Fatalf("Cannot exec rkt: %v", err) } return child }
func spawnOrFail(t *testing.T, cmd string) *gexpect.ExpectSubprocess { t.Logf("Running command: %v", cmd) child, err := gexpect.Spawn(cmd) if err != nil { t.Fatalf("Cannot exec rkt: %v", err) } return child }
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 }
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 = expectTimeoutWithOutput(child, tt.expect, time.Minute) 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) } } }
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") }
/* * 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() }
func removeFromCas(t *testing.T, ctx *rktRunCtx, hash string) { cmd := fmt.Sprintf("%s image rm %s", ctx.cmd(), hash) child, err := gexpect.Spawn(cmd) if err != nil { t.Fatalf("Cannot exec rkt: %v", err) } err = child.Wait() if err != nil { t.Fatalf("rkt didn't terminate correctly: %v", err) } }
func runGC(t *testing.T, ctx *rktRunCtx) { cmd := fmt.Sprintf("%s gc --grace-period=0s", ctx.cmd()) child, err := gexpect.Spawn(cmd) if err != nil { t.Fatalf("Cannot exec rkt: %v", err) } err = child.Wait() if err != nil { t.Fatalf("rkt didn't terminate correctly: %v", err) } }
func TestImageGCTreeStore(t *testing.T) { ctx := testutils.NewRktRunCtx() defer ctx.Cleanup() expectedTreeStores := 2 // If overlayfs is not supported only the stage1 image is rendered in the treeStore if !common.SupportsOverlay() { expectedTreeStores = 1 } // at this point we know that RKT_INSPECT_IMAGE env var is not empty referencedACI := os.Getenv("RKT_INSPECT_IMAGE") cmd := fmt.Sprintf("%s --insecure-skip-verify run --mds-register=false %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) } treeStoreIDs, err := getTreeStoreIDs(ctx) if err != nil { t.Fatalf("unexpected error: %v", err) } // We expect 2 treeStoreIDs for stage1 and app (only 1 if overlay is not supported/enabled) if len(treeStoreIDs) != expectedTreeStores { t.Fatalf("expected %d entries in the treestore but found %d entries", expectedTreeStores, len(treeStoreIDs)) } runImageGC(t, ctx) treeStoreIDs, err = getTreeStoreIDs(ctx) if err != nil { t.Fatalf("unexpected error: %v", err) } // We expect 1/2 treeStoreIDs again as no pod gc has been executed if len(treeStoreIDs) != expectedTreeStores { t.Fatalf("expected %d entries in the treestore but found %d entries", expectedTreeStores, len(treeStoreIDs)) } runGC(t, ctx) runImageGC(t, ctx) treeStoreIDs, err = getTreeStoreIDs(ctx) if err != nil { t.Fatalf("unexpected error: %v", err) } if len(treeStoreIDs) != 0 { t.Fatalf("expected empty treestore but found %d entries", len(treeStoreIDs)) } }
// 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) } }
func TestCaps(t *testing.T) { ctx := newRktRunCtx() defer ctx.cleanup() for i, tt := range capsTests { 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) } stage1FileName := patchTestACI("rkt-inspect-print-caps-stage1.aci", stage1Args...) defer os.Remove(stage1FileName) stage2FileName := patchTestACI("rkt-inspect-print-caps-stage2.aci", stage2Args...) defer os.Remove(stage2FileName) stageFileNames := []string{stage1FileName, 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 --mds-register=false --set-env=CAPABILITY=%d %s", ctx.cmd(), int(tt.capa), stageFileNames[stage-1]) 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() } }
func runRktAndCheckOutput(t *testing.T, rktCmd, expectedLine string) { child, err := gexpect.Spawn(rktCmd) if err != nil { t.Fatalf("cannot exec rkt: %v", err) } if err = expectWithOutput(child, expectedLine); err != nil { t.Fatalf("didn't receive expected output %q: %v", expectedLine, err) } if err = child.Wait(); err != nil { t.Fatalf("rkt didn't terminate correctly: %v", err) } }
func testFetchStoreOnly(t *testing.T, args string, image string, finalURL string) { cannotFetchMsgTpl := `unable to fetch image for .* %s` storeMsgTpl := `using image from local store for .* %s` cannotFetchMsg := fmt.Sprintf(cannotFetchMsgTpl, image) storeMsg := fmt.Sprintf(storeMsgTpl, image) ctx := newRktRunCtx() defer ctx.cleanup() cmd := fmt.Sprintf("%s --store-only %s %s", ctx.cmd(), args, image) t.Logf("Running test %v", cmd) // 1. Run cmd with the image not available in the store should get $cannotFetchMsg. child, err := gexpect.Spawn(cmd) if err != nil { t.Fatalf("Cannot exec rkt: %v", err) } result, out, err := expectRegexWithOutput(child, cannotFetchMsg) if err != nil || len(result) != 1 { t.Fatalf("%q regex must be found one time, Error: %v\nOutput: %v", cannotFetchMsg, err, out) } child.Wait() importImageAndFetchHash(t, ctx, image) // 2. Run cmd with the image available in the store, should get $storeMsg. child, err = gexpect.Spawn(cmd) if err != nil { t.Fatalf("Cannot exec rkt: %v", err) } result, out, err = expectRegexWithOutput(child, storeMsg) if err != nil || len(result) != 1 { t.Fatalf("%q regex must be found one time, Error: %v\nOutput: %v", storeMsg, err, out) } child.Wait() }
func testFetchDefault(t *testing.T, arg string, image string, finalURL string) { remoteFetchMsgTpl := `remote fetching from url %s` storeMsgTpl := `using image from local store for .* %s` if finalURL == "" { finalURL = image } remoteFetchMsg := fmt.Sprintf(remoteFetchMsgTpl, finalURL) storeMsg := fmt.Sprintf(storeMsgTpl, image) ctx := newRktRunCtx() defer ctx.cleanup() cmd := fmt.Sprintf("%s %s %s", ctx.cmd(), arg, image) t.Logf("Running test %v", cmd) // 1. Run cmd with the image not available in the store, should get $remoteFetchMsg. child, err := gexpect.Spawn(cmd) if err != nil { t.Fatalf("Cannot exec rkt: %v", err) } if err := expectWithOutput(child, remoteFetchMsg); err != nil { t.Fatalf("%q should be found", remoteFetchMsg) } child.Wait() // 2. Run cmd with the image available in the store, should get $storeMsg. child, err = gexpect.Spawn(cmd) if err != nil { t.Fatalf("Cannot exec rkt: %v", err) } result, out, err := expectRegexWithOutput(child, storeMsg) if err != nil || len(result) != 1 { t.Fatalf("%q regex must be found one time, Error: %v\nOutput: %v", storeMsg, err, out) } child.Wait() }
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") }
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() }
func getImageId(ctx *rktRunCtx, name string) (string, error) { cmd := fmt.Sprintf(`/bin/sh -c "%s image list --fields=key,name --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 }
func checkAppStatus(t *testing.T, ctx *rktRunCtx, multiApps bool, appName, expected string) { cmd := fmt.Sprintf(`/bin/sh -c "`+ `UUID=$(%s list --full|grep '%s'|awk '{print $1}') ;`+ `echo -n 'status=' ;`+ `%s status $UUID|grep '^app-%s.*=[0-9]*$'|cut -d= -f2"`, ctx.cmd(), appName, ctx.cmd(), appName) if multiApps { cmd = fmt.Sprintf(`/bin/sh -c "`+ `UUID=$(%s list --full|grep '^[a-f0-9]'|awk '{print $1}') ;`+ `echo -n 'status=' ;`+ `%s status $UUID|grep '^app-%s.*=[0-9]*$'|cut -d= -f2"`, ctx.cmd(), ctx.cmd(), appName) } t.Logf("Get status for app %s: %s\n", appName, cmd) child, err := gexpect.Spawn(cmd) if err != nil { t.Fatalf("Cannot exec rkt") } err = expectWithOutput(child, expected) if err != nil { // For debugging purposes, print the full output of // "rkt list" and "rkt status" cmd := fmt.Sprintf(`%s list --full ;`+ `UUID=$(%s list --full|grep '^[a-f0-9]'|awk '{print $1}') ;`+ `%s status $UUID`, ctx.cmd(), ctx.cmd(), ctx.cmd()) out, err2 := exec.Command("/bin/sh", "-c", cmd).CombinedOutput() if err2 != nil { t.Logf("Could not run rkt status: %v. %s", err2, out) } else { t.Logf("%s\n", out) } t.Fatalf("Failed to get the status for app %s: expected: %s. %v", appName, expected, err) } err = child.Wait() if err != nil { t.Fatalf("rkt didn't terminate correctly: %v", err) } }
func TestAceValidator(t *testing.T) { ctx := newRktRunCtx() defer ctx.cleanup() if err := ctx.launchMDS(); err != nil { t.Fatalf("Cannot launch metadata service: %v", err) } tmpDir, err := ioutil.TempDir("", "rkt-TestAceValidator-") if err != nil { t.Fatalf("Cannot create temporary directory: %v", err) } defer os.RemoveAll(tmpDir) aceMain := os.Getenv("RKT_ACE_MAIN_IMAGE") if aceMain == "" { panic("empty RKT_ACE_MAIN_IMAGE env var") } aceSidekick := os.Getenv("RKT_ACE_SIDEKICK_IMAGE") if aceSidekick == "" { panic("empty RKT_ACE_SIDEKICK_IMAGE env var") } rktArgs := fmt.Sprintf("--debug --insecure-skip-verify run --volume database,kind=host,source=%s %s %s", tmpDir, aceMain, aceSidekick) rktCmd := fmt.Sprintf("%s %s", ctx.cmd(), rktArgs) t.Logf("Command: %v", rktCmd) child, err := gexpect.Spawn(rktCmd) if err != nil { t.Fatalf("Cannot exec rkt: %v", err) } for _, e := range expectedResults { err = expectWithOutput(child, e) if err != nil { t.Fatalf("Expected %q but not found: %v", e, err) } } err = child.Wait() if err != nil { t.Fatalf("rkt didn't terminate correctly: %v", err) } }