func runRktTrust(t *testing.T, ctx *testutils.RktRunCtx, prefix string) { var cmd string if prefix == "" { cmd = fmt.Sprintf(`%s trust --root %s`, ctx.Cmd(), "key.gpg") } else { cmd = fmt.Sprintf(`%s trust --prefix %s %s`, ctx.Cmd(), prefix, "key.gpg") } child := spawnOrFail(t, cmd) defer waitOrFail(t, child, true) expected := "Are you sure you want to trust this key" if err := expectWithOutput(child, expected); err != nil { t.Fatalf("Expected but didn't find %q in %v", expected, err) } if err := child.SendLine("yes"); err != nil { t.Fatalf("Cannot confirm rkt trust: %s", err) } if prefix == "" { expected = "Added root key at" } else { expected = fmt.Sprintf(`Added key for prefix "%s" at`, prefix) } if err := expectWithOutput(child, expected); err != nil { t.Fatalf("Expected but didn't find %q in %v", expected, err) } }
func getCreationStartTime(t *testing.T, ctx *testutils.RktRunCtx, imageID string) (creation time.Time, start time.Time) { // Run rkt list --full rktCmd := fmt.Sprintf("%s list --full", ctx.Cmd()) child := spawnOrFail(t, rktCmd) child.Wait() // Get creation time match := fmt.Sprintf(".*%s\t.*\t(.*)\t(.*)\t", imageID) result, out, err := expectRegexWithOutput(child, match) if err != nil { t.Fatalf("%q regex not found, Error: %v\nOutput: %v", match, err, out) } tmStr := strings.TrimSpace(result[1]) creation, err = time.Parse(defaultTimeLayout, tmStr) if err != nil { t.Fatalf("Error parsing creation time: %q", err) } tmStr = strings.TrimSpace(result[2]) start, err = time.Parse(defaultTimeLayout, tmStr) if err != nil { t.Fatalf("Error parsing start time: %q", err) } return creation, start }
func unmountPod(t *testing.T, ctx *testutils.RktRunCtx, uuid string, rmNetns bool) { podDir := filepath.Join(ctx.DataDir(), "pods", "run", uuid) stage1MntPath := filepath.Join(podDir, "stage1", "rootfs") stage2MntPath := filepath.Join(stage1MntPath, "opt", "stage2", "rkt-inspect", "rootfs") netnsPath := filepath.Join(podDir, "netns") podNetNSPathBytes, err := ioutil.ReadFile(netnsPath) if err != nil { t.Fatalf(`cannot read "netns" stage1: %v`, err) } podNetNSPath := string(podNetNSPathBytes) if err := syscall.Unmount(stage2MntPath, 0); err != nil { t.Fatalf("cannot umount stage2: %v", err) } if err := syscall.Unmount(stage1MntPath, 0); err != nil { t.Fatalf("cannot umount stage1: %v", err) } if err := syscall.Unmount(podNetNSPath, 0); err != nil { t.Fatalf("cannot umount pod netns: %v", err) } if rmNetns { _ = os.RemoveAll(podNetNSPath) } }
func patchImportAndRun(image string, patches []string, t *testing.T, ctx *testutils.RktRunCtx) { imagePath := patchTestACI(image, patches...) defer os.Remove(imagePath) cmd := fmt.Sprintf("%s --insecure-skip-verify run %s", ctx.Cmd(), imagePath) spawnAndWaitOrFail(t, cmd, true) }
// waitPodReady waits for the pod supervisor to get ready, busy-looping until `timeout` // while waiting for it. It returns the pod UUID or an error on failure. func waitPodReady(ctx *testutils.RktRunCtx, t *testing.T, uuidFile string, timeout time.Duration) (string, error) { var podUUID []byte var err error interval := 500 * time.Millisecond elapsed := time.Duration(0) for elapsed < timeout { time.Sleep(interval) elapsed += interval podUUID, err = ioutil.ReadFile(uuidFile) if err == nil { break } } if err != nil { return "", fmt.Errorf("Can't read pod UUID: %v", err) } // wait up to one minute for the pod supervisor to be ready cmd := strings.Fields(fmt.Sprintf("%s status --wait-ready=%s %s", ctx.Cmd(), timeout, podUUID)) statusCmd := exec.Command(cmd[0], cmd[1:]...) t.Logf("Running command: %v\n", cmd) output, err := statusCmd.CombinedOutput() if err != nil { return "", fmt.Errorf("Failed to wait for pod readiness, error %v output %v", err, string(output)) } return string(podUUID), nil }
/* * mockFlannelNetwork creates fake flannel network status file and configuration pointing to this network. * We won't have connectivity, but we could check if: netName was correct and if default gateway was set. */ func mockFlannelNetwork(t *testing.T, ctx *testutils.RktRunCtx) (string, networkTemplateT, error) { // write fake flannel info subnetPath := filepath.Join(ctx.DataDir(), "subnet.env") file, err := os.Create(subnetPath) if err != nil { return "", networkTemplateT{}, err } mockedFlannel := strings.Join([]string{ "FLANNEL_NETWORK=11.11.0.0/16", "FLANNEL_SUBNET=11.11.3.1/24", "FLANNEL_MTU=1472", "FLANNEL_IPMASQ=true", }, "\n") if _, err = file.WriteString(mockedFlannel); err != nil { return "", networkTemplateT{}, err } file.Close() // write net config for "flannel" based network ntFlannel := networkTemplateT{ Name: "rkt.kubernetes.io", Type: "flannel", SubnetFile: subnetPath, Delegate: &delegateTemplateT{ IsDefaultGateway: true, }, } netdir := prepareTestNet(t, ctx, ntFlannel) return netdir, ntFlannel, nil }
func startAPIService(t *testing.T, ctx *testutils.RktRunCtx) *gexpect.ExpectSubprocess { noUidGid := false gid, err := common.LookupGid(common.RktGroup) if err != nil { t.Logf("no %q group, will run api service with root, ONLY DO THIS FOR TESTING!", common.RktGroup) noUidGid = true } else { if err := ctx.SetupDataDir(); err != nil { t.Fatalf("failed to setup data directory: %v", err) } } u, err := user.Lookup("nobody") if err != nil { t.Logf(`no "nobody" user, will run api service with root, ONLY DO THIS FOR TESTING!`) noUidGid = true } uid, err := strconv.Atoi(u.Uid) if err != nil { t.Fatalf(`failed to parse "nobody" UID: %v`, err) } t.Logf("Running rkt api service") apisvcCmd := fmt.Sprintf("%s api-service", ctx.Cmd()) if noUidGid { return startRktAndCheckOutput(t, apisvcCmd, "API service running") } return startRktAsUidGidAndCheckOutput(t, apisvcCmd, "API service running", false, uid, gid) }
func prepareTestNet(t *testing.T, ctx *testutils.RktRunCtx, nt networkTemplateT) (netdir string) { configdir := ctx.LocalDir() netdir = filepath.Join(configdir, "net.d") err := os.MkdirAll(netdir, 0644) if err != nil { t.Fatalf("Cannot create netdir: %v", err) } err = writeNetwork(t, nt, netdir) if err != nil { t.Fatalf("Cannot write network file: %v", err) } // If we're proxying the CNI call, then make sure it's in the netdir if nt.Type == "cniproxy" { dest := filepath.Join(netdir, "cniproxy") err := fileutil.CopyRegularFile(testutils.GetValueFromEnvOrPanic("RKT_CNI_PROXY"), dest) if err != nil { t.Fatalf("Cannot copy cniproxy") } os.Chmod(dest, 0755) if err != nil { t.Fatalf("Cannot chmod cniproxy") } } return netdir }
func cleanup(ctx *testutils.RktRunCtx, svc *gexpect.ExpectSubprocess, conn *grpc.ClientConn, imagePath string) { t := new(testing.T) // Print no messages. os.Remove(imagePath) conn.Close() stopAPIService(t, svc) ctx.Cleanup() }
func importImageAndFetchHashAsGid(t *testing.T, ctx *testutils.RktRunCtx, img string, gid int) string { // Import the test image into store manually. cmd := fmt.Sprintf("%s --insecure-skip-verify fetch %s", ctx.Cmd(), img) // TODO(jonboulle): non-root user breaks trying to read root-written // config directories. Should be a better way to approach this. Should // config directories be readable by the rkt group too? if gid != 0 { cmd = fmt.Sprintf("%s --insecure-skip-verify fetch %s", ctx.CmdNoConfig(), img) } child, err := gexpect.Command(cmd) if err != nil { t.Fatalf("cannot create rkt command: %v", err) } if gid != 0 { child.Cmd.SysProcAttr = &syscall.SysProcAttr{} child.Cmd.SysProcAttr.Credential = &syscall.Credential{Uid: nobodyUid, Gid: uint32(gid)} } err = child.Start() if err != nil { t.Fatalf("cannot exec rkt: %v", err) } // Read out the image hash. result, out, err := expectRegexWithOutput(child, "sha512-[0-9a-f]{32}") if err != nil || len(result) != 1 { t.Fatalf("Error: %v\nOutput: %v", err, out) } waitOrFail(t, child, true) return result[0] }
func patchImportAndPrepare(image string, patches []string, t *testing.T, ctx *testutils.RktRunCtx) { imagePath := patchTestACI(image, patches...) defer os.Remove(imagePath) cmd := fmt.Sprintf("%s --insecure-options=image prepare %s", ctx.Cmd(), imagePath) spawnAndWaitOrFail(t, cmd, 0) }
func prepareTestNet(t *testing.T, ctx *testutils.RktRunCtx, nt networkTemplateT) (netdir string) { configdir := ctx.LocalDir() netdir = filepath.Join(configdir, "net.d") err := os.MkdirAll(netdir, 0644) if err != nil { t.Fatalf("Cannot create netdir: %v", err) } err = writeNetwork(t, nt, netdir) if err != nil { t.Fatalf("Cannot write network file: %v", err) } return netdir }
func removeImage(t *testing.T, ctx *testutils.RktRunCtx, images ...string) { cmd := fmt.Sprintf("%s image rm %s", ctx.Cmd(), strings.Join(images, " ")) child, err := gexpect.Spawn(cmd) if err != nil { t.Fatalf("Cannot exec: %v", err) } if err := expectWithOutput(child, rmImageOk); err != nil { t.Fatalf("Expected %q but not found: %v", rmImageOk, err) } if err := child.Wait(); err != nil { t.Fatalf("rkt didn't terminate correctly: %v", err) } }
func launchPods(ctx *testutils.RktRunCtx, numOfPods int, imagePath string) { t := new(testing.T) // Print no messages. cmd := fmt.Sprintf("%s --insecure-options=all run %s", ctx.Cmd(), imagePath) var wg sync.WaitGroup wg.Add(numOfPods) for i := 0; i < numOfPods; i++ { go func() { spawnAndWaitOrFail(t, cmd, true) wg.Done() }() } wg.Wait() }
// getImageInfo returns the image info for the given image ID. func getImageInfo(t *testing.T, ctx *testutils.RktRunCtx, imageID string) *imageInfo { output, err := exec.Command("/bin/bash", "-c", fmt.Sprintf("%s image list --full | grep %s", ctx.Cmd(), imageID)).CombinedOutput() if err != nil { t.Fatalf("Unexpected error: %v", err) } imgInfo := parseImageInfoOutput(t, string(output)) // Get manifest output, err = exec.Command("/bin/bash", "-c", fmt.Sprintf("%s image cat-manifest --pretty-print=false %s", ctx.Cmd(), imageID)).CombinedOutput() if err != nil { t.Fatalf("Unexpected error: %v", err) } imgInfo.manifest = bytes.TrimSuffix(output, []byte{'\n'}) return imgInfo }
func getPodDir(t *testing.T, ctx *testutils.RktRunCtx, podID string) string { podsDir := path.Join(ctx.DataDir(), "pods") dirs, err := ioutil.ReadDir(podsDir) if err != nil { t.Fatalf("Unexpected error: %v", err) } for _, dir := range dirs { podDir := path.Join(podsDir, dir.Name(), podID) if _, err := os.Stat(podDir); err == nil { return podDir } } t.Fatalf("Failed to find pod directory for pod %q", podID) return "" }
func getTreeStoreIDs(ctx *testutils.RktRunCtx) (map[string]struct{}, error) { treeStoreIDs := map[string]struct{}{} ls, err := ioutil.ReadDir(filepath.Join(ctx.DataDir(), "cas", "tree")) if err != nil { if os.IsNotExist(err) { return treeStoreIDs, nil } return nil, fmt.Errorf("cannot read treestore directory: %v", err) } for _, p := range ls { if p.IsDir() { id := filepath.Base(p.Name()) treeStoreIDs[id] = struct{}{} } } return treeStoreIDs, nil }
func removeImage(ctx *testutils.RktRunCtx, image string, shouldWork bool) error { expect := fmt.Sprintf(rmImageReferenced, image) if shouldWork { expect = rmImageOk } cmd := fmt.Sprintf("%s image rm %s", ctx.Cmd(), image) 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 }
func podsRemaining(t *testing.T, ctx *testutils.RktRunCtx) []os.FileInfo { gcDirs := []string{ filepath.Join(ctx.DataDir(), "pods", "exited-garbage"), filepath.Join(ctx.DataDir(), "pods", "prepared"), filepath.Join(ctx.DataDir(), "pods", "garbage"), filepath.Join(ctx.DataDir(), "pods", "run"), } var remainingPods []os.FileInfo for _, dir := range gcDirs { pods, err := ioutil.ReadDir(dir) if err != nil { t.Fatalf("cannot read gc directory %q: %v", dir, err) } remainingPods = append(remainingPods, pods...) } return remainingPods }
// 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 *testutils.RktRunCtx, t *testing.T, host, dir, line string) { // First, check that --insecure-options=image,tls 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) child := spawnOrFail(t, cmd) 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-options=image,tls cmd = fmt.Sprintf(`%s --debug --insecure-options=image,tls run --mds-register=false %s/%s/prog.aci`, ctx.Cmd(), host, dir) child = spawnOrFail(t, cmd) defer child.Wait() if err := expectWithOutput(child, line); err != nil { t.Fatalf("Didn't receive expected output %q: %v", line, err) } }
func capsSeveralAppsRunAndCheckOutput(t *testing.T, ctx *testutils.RktRunCtx, cmd string) { // Ideally, the test would run the pod only one time, but all // apps' output is mixed together without ordering guarantees, so // it makes it impossible to call all the expectWithOutput() in // the correct order. for _, tt := range appCapsTests { t.Logf("Checking caps for %q", tt.testName) child := spawnOrFail(t, cmd) expected := fmt.Sprintf("Capability set: bounding: %s (%s)", tt.expected, tt.testName) if err := expectWithOutput(child, expected); err != nil { t.Fatalf("Expected %q but not found: %v", expected, err) } waitOrFail(t, child, 0) ctx.RunGC() } }
func startAPIService(t *testing.T, ctx *testutils.RktRunCtx) *gexpect.ExpectSubprocess { noGid := false gid, err := common.LookupGid(common.RktGroup) if err != nil { t.Logf("no %q group, will run api service with root, ONLY DO THIS FOR TESTING!", common.RktGroup) noGid = true } else { t.Logf("Running rkt install") installCmd := fmt.Sprintf("%s install", ctx.Cmd()) runRktAndCheckOutput(t, installCmd, "rkt directory structure successfully created", false) } t.Logf("Running rkt api service") apisvcCmd := fmt.Sprintf("%s api-service", ctx.Cmd()) if noGid { return startRktAndCheckOutput(t, apisvcCmd, "API service running") } return startRktAsGidAndCheckOutput(t, apisvcCmd, "API service running", gid) }
func (ct ExportTestCase) Execute(t *testing.T, ctx *testutils.RktRunCtx) { tmpDir := createTempDirOrPanic("rkt-TestExport-tmp-") defer os.RemoveAll(tmpDir) tmpTestAci := filepath.Join(tmpDir, "test.aci") // Prepare the image with modifications var additionalRunArgs string if ct.multiAppPod { tmpAdditionalAci := patchTestACI("other.aci", "--name=other") defer os.Remove(tmpAdditionalAci) const otherArgs = "--write-file --file-name=test.txt --content=NotTheRightContent" additionalRunArgs = fmt.Sprintf("%s --exec=/inspect -- %s", tmpAdditionalAci, otherArgs) } else { additionalRunArgs = "" } const runInspect = "%s %s %s %s --exec=/inspect -- %s --- %s" prepareCmd := fmt.Sprintf(runInspect, ctx.Cmd(), "prepare", ct.runArgs, getInspectImagePath(), ct.writeArgs, additionalRunArgs) t.Logf("Preparing 'inspect --write-file'") uuid := runRktAndGetUUID(t, prepareCmd) runCmd := fmt.Sprintf("%s run-prepared %s", ctx.Cmd(), uuid) t.Logf("Running 'inspect --write-file'") child := spawnOrFail(t, runCmd) waitOrFail(t, child, 0) if ct.unmountOverlay { unmountPod(t, ctx, uuid, true) } // Export the image exportCmd := fmt.Sprintf("%s export %s %s %s", ctx.Cmd(), ct.exportArgs, uuid, tmpTestAci) t.Logf("Running 'export'") child = spawnOrFail(t, exportCmd) waitOrFail(t, child, 0) // Run the newly created ACI and check the output readCmd := fmt.Sprintf(runInspect, ctx.Cmd(), "run", ct.runArgs, tmpTestAci, ct.readArgs, "") t.Logf("Running 'inspect --read-file'") child = spawnOrFail(t, readCmd) if ct.expectedResult != "" { if _, out, err := expectRegexWithOutput(child, ct.expectedResult); err != nil { t.Fatalf("expected %q but not found: %v\n%s", ct.expectedResult, err, out) } } waitOrFail(t, child, 0) // run garbage collector on pods and images runGC(t, ctx) runImageGC(t, ctx) }
// getPodInfo returns the pod info for the given pod ID. func getPodInfo(t *testing.T, ctx *testutils.RktRunCtx, podID string) *podInfo { p := &podInfo{ id: podID, apps: make(map[string]*appInfo), networks: make(map[string]*networkInfo), } // Read pod manifest. output, err := exec.Command("/bin/bash", "-c", fmt.Sprintf("%s cat-manifest %s", ctx.Cmd(), podID)).CombinedOutput() if err != nil { t.Fatalf("Unexpected error: %v", err) } // Trim the last '\n' character. p.manifest = bytes.TrimSpace(output) // Fill app infos. var manifest schema.PodManifest if err := json.Unmarshal(p.manifest, &manifest); err != nil { t.Fatalf("Unexpected error: %v", err) } for _, app := range manifest.Apps { appName := app.Name.String() p.apps[appName] = &appInfo{ name: appName, // TODO(yifan): Get the image's name. image: &imageInfo{id: app.Image.ID.String()}, } } // Fill other infos. output, err = exec.Command("/bin/bash", "-c", fmt.Sprintf("%s status %s", ctx.Cmd(), podID)).CombinedOutput() if err != nil { t.Fatalf("Unexpected error: %v", err) } parsePodInfoOutput(t, string(output), p) return p }
func importImageAndFetchHashAsGid(t *testing.T, ctx *testutils.RktRunCtx, img string, fetchArgs string, gid int) (string, error) { // Import the test image into store manually. cmd := fmt.Sprintf("%s --insecure-options=image,tls fetch %s %s", ctx.Cmd(), fetchArgs, img) // TODO(jonboulle): non-root user breaks trying to read root-written // config directories. Should be a better way to approach this. Should // config directories be readable by the rkt group too? if gid != 0 { cmd = fmt.Sprintf("%s --insecure-options=image,tls fetch %s %s", ctx.CmdNoConfig(), fetchArgs, img) } child, err := gexpect.Command(cmd) if err != nil { t.Fatalf("cannot create rkt command: %v", err) } if gid != 0 { child.Cmd.SysProcAttr = &syscall.SysProcAttr{} child.Cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uint32(nobodyUid), Gid: uint32(gid)} } err = child.Start() if err != nil { t.Fatalf("cannot exec rkt: %v", err) } // Read out the image hash. result, out, err := expectRegexWithOutput(child, "sha512-[0-9a-f]{32,64}") if err != nil || len(result) != 1 { t.Fatalf("Error: %v\nOutput: %v", err, out) } err = child.Wait() status := getExitStatus(err) if status != 0 { t.Logf("rkt terminated with unexpected status %d, expected %d\nOutput:\n%s", status, 0, child.Collect()) return "", fmt.Errorf("fetching of %q failed", img) } return result[0], nil }
func preparePidFileRace(t *testing.T, ctx *testutils.RktRunCtx, sleepImage string) (*gexpect.ExpectSubprocess, *gexpect.ExpectSubprocess, string, string) { // Start the pod runCmd := fmt.Sprintf("%s --debug --insecure-options=image run --mds-register=false --interactive %s", ctx.Cmd(), sleepImage) runChild := spawnOrFail(t, runCmd) if err := expectWithOutput(runChild, "Enter text:"); 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 := spawnOrFail(t, enterCmd) // Enter should be able to wait until the ppid file appears time.Sleep(1 * time.Second) return runChild, enterChild, pidFileName, pidFileNameBackup }
// waitPodReady waits for the pod supervisor to get ready, busy-looping until `timeout` // while waiting for it. It returns the pod UUID or an error on failure. func waitPodReady(ctx *testutils.RktRunCtx, uuidFile string, timeout time.Duration) (string, error) { var podUUID []byte var err error interval := 500 * time.Millisecond elapsed := time.Duration(0) for elapsed < timeout { time.Sleep(interval) elapsed += interval podUUID, err = ioutil.ReadFile(uuidFile) if err == nil { break } } if err != nil { return "", fmt.Errorf("Can't read pod UUID: %v", err) } // wait for the pod supervisor to be ready podReadyFile := filepath.Join(ctx.DataDir(), "pods", "run", string(podUUID), "stage1/rootfs/rkt/supervisor-status") target := "" elapsed = time.Duration(0) for elapsed < timeout { time.Sleep(interval) elapsed += interval target, err = os.Readlink(podReadyFile) if err == nil && target == "ready" { break } } if err != nil || target != "ready" { return "", fmt.Errorf("Pod failed to become ready while checking %q", podReadyFile) } return string(podUUID), nil }
func getImageID(ctx *testutils.RktRunCtx, name string) (string, error) { cmd := fmt.Sprintf(`/bin/sh -c "%s image list --fields=id,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 getImageName(t *testing.T, ctx *testutils.RktRunCtx, name string) string { cmd := fmt.Sprintf(`/bin/sh -c "%s image list --fields=name --no-legend | grep %s | cut -d: -f1"`, ctx.Cmd(), name) child := spawnOrFail(t, cmd) imageName, err := child.ReadLine() imageName = strings.TrimSpace(imageName) imageName = string(bytes.Trim([]byte(imageName), "\x00")) if err != nil { t.Fatalf("Cannot exec: %v", err) } waitOrFail(t, child, true) return imageName }
func runImage(t *testing.T, ctx *testutils.RktRunCtx, imageFile string, expected string, shouldFail bool) { cmd := fmt.Sprintf(`%s --debug run --mds-register=false %s`, ctx.Cmd(), imageFile) runRktAndCheckOutput(t, cmd, expected, shouldFail) }