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 }
// 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 }
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 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 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) }
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 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 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 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 }
// 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 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 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 }
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 checkAppStatus(t *testing.T, ctx *testutils.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\n", appName) child := spawnOrFail(t, cmd) defer waitOrFail(t, child, true) if err := expectWithOutput(child, expected); 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) } }
func runImageGC(t *testing.T, ctx *testutils.RktRunCtx) { cmd := fmt.Sprintf("%s image gc", ctx.Cmd()) spawnAndWaitOrFail(t, cmd, true) }
func runGC(t *testing.T, ctx *testutils.RktRunCtx) { cmd := fmt.Sprintf("%s gc --grace-period=0s", ctx.Cmd()) spawnAndWaitOrFail(t, cmd, true) }
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 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 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) }
func removeFromCas(t *testing.T, ctx *testutils.RktRunCtx, hash string) { cmd := fmt.Sprintf("%s image rm %s", ctx.Cmd(), hash) spawnAndWaitOrFail(t, cmd, true) }
func (ct PortFwdCase) Execute(t *testing.T, ctx *testutils.RktRunCtx) { netdir := prepareTestNet(t, ctx, portFwdBridge) defer os.RemoveAll(netdir) httpPort, err := testutils.GetNextFreePort4Banned(bannedPorts) if err != nil { t.Fatalf("%v", err) } bannedPorts[httpPort] = struct{}{} httpServePort := ct.HttpServePort if httpServePort == 0 { httpServePort = httpPort } httpServeAddr := fmt.Sprintf("0.0.0.0:%d", httpServePort) testImageArgs := []string{ fmt.Sprintf("--ports=http,protocol=tcp,port=%d", httpServePort), fmt.Sprintf("--exec=/inspect --serve-http=%v", httpServeAddr), } t.Logf("testImageArgs: %v", testImageArgs) testImage := patchTestACI("rkt-inspect-networking.aci", testImageArgs...) defer os.Remove(testImage) cmd := fmt.Sprintf( "%s --debug --insecure-options=image run --port=http:%s%d %s --mds-register=false %s", ctx.Cmd(), ct.ListenAddress, httpPort, ct.RktArg, testImage) child := spawnOrFail(t, cmd) httpGetAddr := fmt.Sprintf("http://%v:%v", ct.HttpGetIP, httpPort) ga := testutils.NewGoroutineAssistant(t) ga.Add(2) // Child opens the server go func() { defer ga.Done() ga.WaitOrFail(child) }() // Host connects to the child via the forward port on localhost go func() { defer ga.Done() expectedRegex := `serving on` _, out, err := expectRegexWithOutput(child, expectedRegex) if err != nil { ga.Fatalf("Error: %v\nOutput: %v", err, out) } body, err := testutils.HTTPGet(httpGetAddr) switch { case err != nil && ct.ShouldSucceed: ga.Fatalf("%v\n", err) case err == nil && !ct.ShouldSucceed: ga.Fatalf("HTTP-Get to %q should have failed! But received %q", httpGetAddr, body) case err != nil && !ct.ShouldSucceed: t.Logf("HTTP-Get failed, as expected: %v", err) default: t.Logf("HTTP-Get received: %s", body) } }() ga.Wait() }
func importImageAndPrepare(imagePath string, t *testing.T, ctx *testutils.RktRunCtx) { cmd := fmt.Sprintf("%s --insecure-options=image prepare %s", ctx.Cmd(), imagePath) spawnAndWaitOrFail(t, cmd, 0) }
func getMissingOrInvalidTests(t *testing.T, ctx *testutils.RktRunCtx) []osArchTest { var tests []osArchTest defer osArchTestRemoveImages(tests) testImageName := "coreos.com/rkt-missing-os-arch-test" manifest := strings.Replace(manifestOSArchTemplate, "IMG_NAME", testImageName, 1) // Test a valid image as a sanity check goodManifestStr := strings.Replace(manifest, "ARCH_OS", `,{"name":"os","value":"linux"},{"name":"arch","value":"amd64"}`, 1) goodManifestFile := "good-manifest.json" if err := ioutil.WriteFile(goodManifestFile, []byte(goodManifestStr), 0600); err != nil { t.Fatalf("Cannot write good manifest: %v", err) } defer os.Remove(goodManifestFile) goodImage := patchTestACI("rkt-good-image.aci", fmt.Sprintf("--manifest=%s", goodManifestFile)) goodTest := osArchTest{ image: goodImage, rktCmd: fmt.Sprintf("%s --insecure-options=image run --mds-register=false %s", ctx.Cmd(), goodImage), expectedLine: "HelloWorld", expectError: false, } tests = append(tests, goodTest) // Test an image with a missing os label missingOSManifestStr := strings.Replace(manifest, "ARCH_OS", `,{"name":"arch","value":"amd64"}`, 1) missingOSManifestFile := "missingOS-manifest.json" if err := ioutil.WriteFile(missingOSManifestFile, []byte(missingOSManifestStr), 0600); err != nil { t.Fatalf("Cannot write missing OS manifest: %v", err) } defer os.Remove(missingOSManifestFile) missingOSImage := patchTestACI("rkt-missing-os.aci", fmt.Sprintf("--manifest=%s", missingOSManifestFile)) missingOSTest := osArchTest{ image: missingOSImage, rktCmd: fmt.Sprintf("%s --insecure-options=image run %s", ctx.Cmd(), missingOSImage), expectedLine: "missing os label in the image manifest", expectError: true, } tests = append(tests, missingOSTest) // Test an image with a missing arch label missingArchManifestStr := strings.Replace(manifest, "ARCH_OS", `,{"name":"os","value":"linux"}`, 1) missingArchManifestFile := "missingArch-manifest.json" if err := ioutil.WriteFile(missingArchManifestFile, []byte(missingArchManifestStr), 0600); err != nil { t.Fatalf("Cannot write missing Arch manifest: %v", err) } defer os.Remove(missingArchManifestFile) missingArchImage := patchTestACI("rkt-missing-arch.aci", fmt.Sprintf("--manifest=%s", missingArchManifestFile)) missingArchTest := osArchTest{ image: missingArchImage, rktCmd: fmt.Sprintf("%s --insecure-options=image run %s", ctx.Cmd(), missingArchImage), expectedLine: "missing arch label in the image manifest", expectError: true, } tests = append(tests, missingArchTest) // Test an image with an invalid os invalidOSManifestStr := strings.Replace(manifest, "ARCH_OS", `,{"name":"os","value":"freebsd"},{"name":"arch","value":"amd64"}`, 1) invalidOSManifestFile := "invalid-os-manifest.json" if err := ioutil.WriteFile(invalidOSManifestFile, []byte(invalidOSManifestStr), 0600); err != nil { t.Fatalf("Cannot write invalid os manifest: %v", err) } defer os.Remove(invalidOSManifestFile) invalidOSImage := patchTestACI("rkt-invalid-os.aci", fmt.Sprintf("--manifest=%s", invalidOSManifestFile)) invalidOSTest := osArchTest{ image: invalidOSImage, rktCmd: fmt.Sprintf("%s --insecure-options=image run %s", ctx.Cmd(), invalidOSImage), expectedLine: `bad os "freebsd"`, expectError: true, } tests = append(tests, invalidOSTest) // Test an image with an invalid arch invalidArchManifestStr := strings.Replace(manifest, "ARCH_OS", `,{"name":"os","value":"linux"},{"name":"arch","value":"armv5l"}`, 1) invalidArchManifestFile := "invalid-arch-manifest.json" if err := ioutil.WriteFile(invalidArchManifestFile, []byte(invalidArchManifestStr), 0600); err != nil { t.Fatalf("Cannot write invalid arch manifest: %v", err) } defer os.Remove(invalidArchManifestFile) retTests := tests tests = nil return retTests }