func TestAceValidator(t *testing.T) { newStringSet := func(strs ...string) map[string]struct{} { m := make(map[string]struct{}, len(strs)) for _, s := range strs { m[s] = struct{}{} } return m } expected := []map[string]struct{}{ newStringSet("prestart"), newStringSet("main", "sidekick"), // newStringSet("poststop"), // Disabled by caseyc for #2870 } pattern := `ace-validator-(?:main|sidekick)\[\d+\]: ([[:alpha:]]+) OK` ctx := testutils.NewRktRunCtx() defer ctx.Cleanup() if err := ctx.LaunchMDS(); err != nil { t.Fatalf("Cannot launch metadata service: %v", err) } aceMain := testutils.GetValueFromEnvOrPanic("RKT_ACE_MAIN_IMAGE") aceSidekick := testutils.GetValueFromEnvOrPanic("RKT_ACE_SIDEKICK_IMAGE") rktArgs := fmt.Sprintf("--debug --insecure-options=image run --mds-register --volume database,kind=empty %s %s", aceMain, aceSidekick) rktCmd := fmt.Sprintf("%s %s", ctx.Cmd(), rktArgs) child := spawnOrFail(t, rktCmd) defer waitOrFail(t, child, 0) out := "" for _, set := range expected { for len(set) > 0 { results, o, err := expectRegexWithOutput(child, pattern) out += o if err != nil { var keys []string for k := range set { keys = append(keys, fmt.Sprintf("%q", k)) } ex := strings.Join(keys, " or ") t.Fatalf("Expected %s, but not found: %v\nOutput: %v", ex, err, out) } if len(results) != 2 { t.Fatalf("Unexpected regex results, expected a whole match and one submatch, got %#v", results) } aceStage := results[1] if _, ok := set[aceStage]; ok { t.Logf("Got expected ACE stage %q", aceStage) delete(set, aceStage) } else { t.Logf("Ignoring unknown ACE stage %q", aceStage) } } } }
func runServer(t *testing.T, auth taas.Type) *taas.Server { actool := testutils.GetValueFromEnvOrPanic("ACTOOL") gotool := testutils.GetValueFromEnvOrPanic("GO") server, err := taas.NewServerWithPaths(auth, 20, actool, gotool) if err != nil { t.Fatalf("Could not start server: %v", err) } go serverHandler(t, server) return server }
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 patchACI(inputFileName, newFileName string, args ...string) string { var allArgs []string actool := testutils.GetValueFromEnvOrPanic("ACTOOL") tmpDir := testutils.GetValueFromEnvOrPanic("FUNCTIONAL_TMP") imagePath, err := filepath.Abs(filepath.Join(tmpDir, newFileName)) if err != nil { panic(fmt.Sprintf("Cannot create ACI: %v\n", err)) } allArgs = append(allArgs, "patch-manifest") allArgs = append(allArgs, "--no-compression") allArgs = append(allArgs, "--overwrite") allArgs = append(allArgs, args...) allArgs = append(allArgs, inputFileName) allArgs = append(allArgs, imagePath) output, err := exec.Command(actool, allArgs...).CombinedOutput() if err != nil { panic(fmt.Sprintf("Cannot create ACI: %v: %s\n", err, output)) } return imagePath }
func generatePodManifestFile(t *testing.T, manifest *schema.PodManifest) string { tmpDir := testutils.GetValueFromEnvOrPanic("FUNCTIONAL_TMP") f, err := ioutil.TempFile(tmpDir, "rkt-test-manifest-") if err != nil { t.Fatalf("Cannot create tmp pod manifest: %v", err) } data, err := json.Marshal(manifest) if err != nil { t.Fatalf("Cannot marshal pod manifest: %v", err) } if err := ioutil.WriteFile(f.Name(), data, 0600); err != nil { t.Fatalf("Cannot write pod manifest file: %v", err) } return f.Name() }
func newStubStage1Setup(t *testing.T, serverSetup *taas.ServerSetup) *stubStage1Setup { ctx := testutils.NewRktRunCtx() defer func() { if ctx != nil { ctx.Cleanup() } }() var server *taas.Server stubStage1 := testutils.GetValueFromEnvOrPanic("STUB_STAGE1") if serverSetup != nil { server = runServer(t, serverSetup) defer func() { if server != nil { server.Close() } }() fileSet := map[string]string{ filepath.Base(stubStage1): stubStage1, } if err := server.UpdateFileSet(fileSet); err != nil { t.Fatalf("Failed to populate a file list in test aci server: %v", err) } } setup := &stubStage1Setup{ t: t, ctx: ctx, server: server, name: "localhost/rkt-stub-stage1", version: "0.0.1", path: stubStage1, } ctx = nil server = nil return setup }
// 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 := getInspectImagePath() emptyImage := getEmptyImagePath() testImageName := "coreos.com/rkt-image-render-test" inspectFile := testutils.GetValueFromEnvOrPanic("INSPECT_BINARY") inspectHash := getHashOrPanic(inspectFile) expectManifest := strings.Replace(manifestRenderTemplate, "IMG_NAME", testImageName, -1) tmpDir := createTempDirOrPanic("rkt-TestImageRender-") 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 := testutils.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) spawnAndWaitOrFail(t, runCmd, tt.shouldFind) if !tt.shouldFind { continue } 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) } } }
// TestImageExtract tests 'rkt image extract', it will import some existing // image with the inspect binary, extract it with rkt image extract and check // that the exported /inspect hash matches the original inspect binary hash func TestImageExtract(t *testing.T) { testImage := getInspectImagePath() testImageName := "coreos.com/rkt-inspect" inspectFile := testutils.GetValueFromEnvOrPanic("INSPECT_BINARY") inspectHash := getHashOrPanic(inspectFile) tmpDir := createTempDirOrPanic("rkt-TestImageRender-") defer os.RemoveAll(tmpDir) ctx := testutils.NewRktRunCtx() defer ctx.Cleanup() 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("extracted-%d", i)) runCmd := fmt.Sprintf("%s image extract --rootfs-only %s %s", ctx.Cmd(), tt.image, outputPath) t.Logf("Running 'image extract' test #%v: %v", i, runCmd) spawnAndWaitOrFail(t, runCmd, tt.shouldFind) if !tt.shouldFind { continue } extractedInspectHash, err := getHash(filepath.Join(outputPath, "inspect")) if err != nil { t.Fatalf("Cannot get rendered inspect binary's hash") } if extractedInspectHash != tt.expectedHash { t.Fatalf("Expected /inspect hash %q but got %s", tt.expectedHash, extractedInspectHash) } } }
func getInspectImagePath() string { return testutils.GetValueFromEnvOrPanic("RKT_INSPECT_IMAGE") }
func getEmptyImagePath() string { return testutils.GetValueFromEnvOrPanic("RKT_EMPTY_IMAGE") }
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) printTermHostImage := patchTestACI("rkt-inspect-print-term-host.aci", "--exec=/inspect --print-env=TERM") defer os.Remove(printTermHostImage) checkPathImage := patchTestACI("rkt-inspect-check-path.aci", "--exec=/inspect --check-path") defer os.Remove(checkPathImage) sleepImage := patchTestACI("rkt-inspect-sleep.aci", "--exec=/inspect --read-stdin") defer os.Remove(sleepImage) ctx := testutils.NewRktRunCtx() defer ctx.Cleanup() term := testutils.GetValueFromEnvOrPanic("TERM") 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, "^PRINT_TERM_HOST^", printTermHostImage, -1) fixed = strings.Replace(fixed, "^CHECK_PATH^", checkPathImage, -1) fixed = strings.Replace(fixed, "^SLEEP^", sleepImage, -1) fixed = strings.Replace(fixed, "^HOST_TERM^", term, -1) return fixed } for i, tt := range envTests { // change dynamic variables from expected result tt.runExpect = replacePlaceholders(tt.runExpect) // 'run' tests runCmd := replacePlaceholders(tt.runCmd) t.Logf("Running 'run' test #%v", i) runRktAndCheckOutput(t, runCmd, tt.runExpect, false) // 'enter' tests sleepCmd := replacePlaceholders(tt.sleepCmd) t.Logf("Running 'enter' test #%v", i) child := spawnOrFail(t, sleepCmd) if err := expectWithOutput(child, "Enter text:"); 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", i) enterChild := spawnOrFail(t, enterCmd) if err := expectWithOutput(enterChild, tt.runExpect); err != nil { t.Fatalf("Expected %q but not found: %v", tt.runExpect, err) } waitOrFail(t, enterChild, 0) if err := child.SendLine("Bye"); err != nil { t.Fatalf("rkt couldn't write to the container: %v", err) } if err := expectWithOutput(child, "Received text: Bye"); err != nil { t.Fatalf("Expected Bye but not found #%v: %v", i, err) } waitOrFail(t, child, 0) ctx.Reset() } }