diff options
Diffstat (limited to 'test/e2e/libpod_suite_test.go')
-rw-r--r-- | test/e2e/libpod_suite_test.go | 475 |
1 files changed, 54 insertions, 421 deletions
diff --git a/test/e2e/libpod_suite_test.go b/test/e2e/libpod_suite_test.go index ec274cc34..52507c083 100644 --- a/test/e2e/libpod_suite_test.go +++ b/test/e2e/libpod_suite_test.go @@ -1,22 +1,18 @@ package integration import ( - "bufio" - "context" "encoding/json" "fmt" "io/ioutil" "os" "os/exec" "path/filepath" - "runtime" "strings" "testing" - "time" "github.com/containers/libpod/libpod" "github.com/containers/libpod/pkg/inspect" - "github.com/containers/storage/pkg/parsers/kernel" + . "github.com/containers/libpod/test/utils" "github.com/containers/storage/pkg/reexec" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -35,14 +31,9 @@ var ( defaultWaitTimeout = 90 ) -// PodmanSession wrapps the gexec.session so we can extend it -type PodmanSession struct { - *gexec.Session -} - -// PodmanTest struct for command line options -type PodmanTest struct { - PodmanBinary string +// PodmanTestIntegration struct for command line options +type PodmanTestIntegration struct { + PodmanTest ConmonBinary string CrioRoot string CNIConfigDir string @@ -50,17 +41,13 @@ type PodmanTest struct { RunRoot string StorageOptions string SignaturePolicyPath string - ArtifactPath string - TempDir string CgroupManager string Host HostOS } -// HostOS is a simple struct for the test os -type HostOS struct { - Distribution string - Version string - Arch string +// PodmanSessionIntegration sturct for command line session +type PodmanSessionIntegration struct { + *PodmanSession } // TestLibpod ginkgo master function @@ -80,7 +67,7 @@ var _ = BeforeSuite(func() { //Cache images cwd, _ := os.Getwd() INTEGRATION_ROOT = filepath.Join(cwd, "../../") - podman := PodmanCreate("/tmp") + podman := PodmanTestCreate("/tmp") podman.ArtifactPath = ARTIFACT_DIR if _, err := os.Stat(ARTIFACT_DIR); os.IsNotExist(err) { if err = os.Mkdir(ARTIFACT_DIR, 0777); err != nil { @@ -110,13 +97,8 @@ var _ = BeforeSuite(func() { } }) -// CreateTempDirin -func CreateTempDirInTempDir() (string, error) { - return ioutil.TempDir("", "podman_test") -} - -// PodmanCreate creates a PodmanTest instance for the tests -func PodmanCreate(tempDir string) PodmanTest { +// PodmanTestCreate creates a PodmanTestIntegration instance for the tests +func PodmanTestCreate(tempDir string) *PodmanTestIntegration { host := GetHostDistributionInfo() cwd, _ := os.Getwd() @@ -157,8 +139,12 @@ func PodmanCreate(tempDir string) PodmanTest { CNIConfigDir := "/etc/cni/net.d" - p := PodmanTest{ - PodmanBinary: podmanBinary, + p := &PodmanTestIntegration{ + PodmanTest: PodmanTest{ + PodmanBinary: podmanBinary, + ArtifactPath: ARTIFACT_DIR, + TempDir: tempDir, + }, ConmonBinary: conmonBinary, CrioRoot: filepath.Join(tempDir, "crio"), CNIConfigDir: CNIConfigDir, @@ -166,73 +152,50 @@ func PodmanCreate(tempDir string) PodmanTest { RunRoot: filepath.Join(tempDir, "crio-run"), StorageOptions: storageOptions, SignaturePolicyPath: filepath.Join(INTEGRATION_ROOT, "test/policy.json"), - ArtifactPath: ARTIFACT_DIR, - TempDir: tempDir, CgroupManager: cgroupManager, Host: host, } // Setup registries.conf ENV variable p.setDefaultRegistriesConfigEnv() + // Rewrite the PodmanAsUser function + p.PodmanMakeOptions = p.makeOptions return p } //MakeOptions assembles all the podman main options -func (p *PodmanTest) MakeOptions() []string { - return strings.Split(fmt.Sprintf("--root %s --runroot %s --runtime %s --conmon %s --cni-config-dir %s --cgroup-manager %s", +func (p *PodmanTestIntegration) makeOptions(args []string) []string { + podmanOptions := strings.Split(fmt.Sprintf("--root %s --runroot %s --runtime %s --conmon %s --cni-config-dir %s --cgroup-manager %s", p.CrioRoot, p.RunRoot, p.RunCBinary, p.ConmonBinary, p.CNIConfigDir, p.CgroupManager), " ") -} - -// Podman is the exec call to podman on the filesystem, uid and gid the credentials to use -func (p *PodmanTest) PodmanAsUser(args []string, uid, gid uint32, env []string) *PodmanSession { - podmanOptions := p.MakeOptions() if os.Getenv("HOOK_OPTION") != "" { podmanOptions = append(podmanOptions, os.Getenv("HOOK_OPTION")) } podmanOptions = append(podmanOptions, strings.Split(p.StorageOptions, " ")...) podmanOptions = append(podmanOptions, args...) - if env == nil { - fmt.Printf("Running: %s %s\n", p.PodmanBinary, strings.Join(podmanOptions, " ")) - } else { - fmt.Printf("Running: (env: %v) %s %s\n", env, p.PodmanBinary, strings.Join(podmanOptions, " ")) - } - var command *exec.Cmd - - if uid != 0 || gid != 0 { - nsEnterOpts := append([]string{"--userspec", fmt.Sprintf("%d:%d", uid, gid), "/", p.PodmanBinary}, podmanOptions...) - command = exec.Command("chroot", nsEnterOpts...) - } else { - command = exec.Command(p.PodmanBinary, podmanOptions...) - } - if env != nil { - command.Env = env - } - - session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) - if err != nil { - Fail(fmt.Sprintf("unable to run podman command: %s\n%v", strings.Join(podmanOptions, " "), err)) - } - return &PodmanSession{session} + return podmanOptions } // Podman is the exec call to podman on the filesystem -func (p *PodmanTest) Podman(args []string) *PodmanSession { - return p.PodmanAsUser(args, 0, 0, nil) +func (p *PodmanTestIntegration) Podman(args []string) *PodmanSessionIntegration { + podmanSession := p.PodmanBase(args) + return &PodmanSessionIntegration{podmanSession} } -//WaitForContainer waits on a started container -func WaitForContainer(p *PodmanTest) bool { - for i := 0; i < 10; i++ { - if p.NumberOfRunningContainers() == 1 { - return true - } - time.Sleep(1 * time.Second) +// PodmanPID execs podman and returns its PID +func (p *PodmanTestIntegration) PodmanPID(args []string) (*PodmanSessionIntegration, int) { + podmanOptions := p.MakeOptions(args) + fmt.Printf("Running: %s %s\n", p.PodmanBinary, strings.Join(podmanOptions, " ")) + command := exec.Command(p.PodmanBinary, podmanOptions...) + session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) + if err != nil { + Fail(fmt.Sprintf("unable to run podman command: %s", strings.Join(podmanOptions, " "))) } - return false + podmanSession := &PodmanSession{session} + return &PodmanSessionIntegration{podmanSession}, command.Process.Pid } // Cleanup cleans up the temporary store -func (p *PodmanTest) Cleanup() { +func (p *PodmanTestIntegration) Cleanup() { // Remove all containers stopall := p.Podman([]string{"stop", "-a", "--timeout", "0"}) stopall.WaitWithDefaultTimeout() @@ -248,7 +211,7 @@ func (p *PodmanTest) Cleanup() { } // CleanupPod cleans up the temporary store -func (p *PodmanTest) CleanupPod() { +func (p *PodmanTestIntegration) CleanupPod() { // Remove all containers session := p.Podman([]string{"pod", "rm", "-fa"}) session.Wait(90) @@ -258,103 +221,26 @@ func (p *PodmanTest) CleanupPod() { } } -// GrepString takes session output and behaves like grep. it returns a bool -// if successful and an array of strings on positive matches -func (s *PodmanSession) GrepString(term string) (bool, []string) { - var ( - greps []string - matches bool - ) - - for _, line := range strings.Split(s.OutputToString(), "\n") { - if strings.Contains(line, term) { - matches = true - greps = append(greps, line) - } - } - return matches, greps -} - -// Pull Images pulls multiple images -func (p *PodmanTest) PullImages(images []string) error { +// PullImages pulls multiple images +func (p *PodmanTestIntegration) PullImages(images []string) error { for _, i := range images { p.PullImage(i) } return nil } -// Pull Image a single image +// PullImage pulls a single image // TODO should the timeout be configurable? -func (p *PodmanTest) PullImage(image string) error { +func (p *PodmanTestIntegration) PullImage(image string) error { session := p.Podman([]string{"pull", image}) session.Wait(60) Expect(session.ExitCode()).To(Equal(0)) return nil } -// OutputToString formats session output to string -func (s *PodmanSession) OutputToString() string { - fields := strings.Fields(fmt.Sprintf("%s", s.Out.Contents())) - return strings.Join(fields, " ") -} - -// OutputToStringArray returns the output as a []string -// where each array item is a line split by newline -func (s *PodmanSession) OutputToStringArray() []string { - var results []string - output := fmt.Sprintf("%s", s.Out.Contents()) - for _, line := range strings.Split(output, "\n") { - if line != "" { - results = append(results, line) - } - } - return results -} - -// ErrorGrepString takes session stderr output and behaves like grep. it returns a bool -// if successful and an array of strings on positive matches -func (s *PodmanSession) ErrorGrepString(term string) (bool, []string) { - var ( - greps []string - matches bool - ) - - for _, line := range strings.Split(s.ErrorToString(), "\n") { - if strings.Contains(line, term) { - matches = true - greps = append(greps, line) - } - } - return matches, greps -} - -// ErrorToString formats session stderr to string -func (s *PodmanSession) ErrorToString() string { - fields := strings.Fields(fmt.Sprintf("%s", s.Err.Contents())) - return strings.Join(fields, " ") -} - -// ErrorToStringArray returns the stderr output as a []string -// where each array item is a line split by newline -func (s *PodmanSession) ErrorToStringArray() []string { - output := fmt.Sprintf("%s", s.Err.Contents()) - return strings.Split(output, "\n") -} - -// IsJSONOutputValid attempts to unmarshal the session buffer -// and if successful, returns true, else false -func (s *PodmanSession) IsJSONOutputValid() bool { - var i interface{} - if err := json.Unmarshal(s.Out.Contents(), &i); err != nil { - fmt.Println(err) - return false - } - return true -} - // InspectContainerToJSON takes the session output of an inspect // container and returns json -func (s *PodmanSession) InspectContainerToJSON() []inspect.ContainerData { +func (s *PodmanSessionIntegration) InspectContainerToJSON() []inspect.ContainerData { var i []inspect.ContainerData err := json.Unmarshal(s.Out.Contents(), &i) Expect(err).To(BeNil()) @@ -362,7 +248,7 @@ func (s *PodmanSession) InspectContainerToJSON() []inspect.ContainerData { } // InspectPodToJSON takes the sessions output from a pod inspect and returns json -func (s *PodmanSession) InspectPodToJSON() libpod.PodInspect { +func (s *PodmanSessionIntegration) InspectPodToJSON() libpod.PodInspect { var i libpod.PodInspect err := json.Unmarshal(s.Out.Contents(), &i) Expect(err).To(BeNil()) @@ -371,30 +257,15 @@ func (s *PodmanSession) InspectPodToJSON() libpod.PodInspect { // InspectImageJSON takes the session output of an inspect // image and returns json -func (s *PodmanSession) InspectImageJSON() []inspect.ImageData { +func (s *PodmanSessionIntegration) InspectImageJSON() []inspect.ImageData { var i []inspect.ImageData err := json.Unmarshal(s.Out.Contents(), &i) Expect(err).To(BeNil()) return i } -func (s *PodmanSession) WaitWithDefaultTimeout() { - s.Wait(defaultWaitTimeout) - fmt.Println("output:", s.OutputToString()) -} - -// SystemExec is used to exec a system command to check its exit code or output -func (p *PodmanTest) SystemExec(command string, args []string) *PodmanSession { - c := exec.Command(command, args...) - session, err := gexec.Start(c, GinkgoWriter, GinkgoWriter) - if err != nil { - Fail(fmt.Sprintf("unable to run command: %s %s", command, strings.Join(args, " "))) - } - return &PodmanSession{session} -} - // CreateArtifact creates a cached image in the artifact dir -func (p *PodmanTest) CreateArtifact(image string) error { +func (p *PodmanTestIntegration) CreateArtifact(image string) error { if os.Getenv("NO_TEST_CACHE") != "" { return nil } @@ -415,7 +286,7 @@ func (p *PodmanTest) CreateArtifact(image string) error { } // RestoreArtifact puts the cached image into our test store -func (p *PodmanTest) RestoreArtifact(image string) error { +func (p *PodmanTestIntegration) RestoreArtifact(image string) error { fmt.Printf("Restoring %s...\n", image) dest := strings.Split(image, "/") destName := fmt.Sprintf("/tmp/%s.tar", strings.Replace(strings.Join(strings.Split(dest[len(dest)-1], "/"), ""), ":", "-", -1)) @@ -425,7 +296,7 @@ func (p *PodmanTest) RestoreArtifact(image string) error { } // RestoreAllArtifacts unpacks all cached images -func (p *PodmanTest) RestoreAllArtifacts() error { +func (p *PodmanTestIntegration) RestoreAllArtifacts() error { if os.Getenv("NO_TEST_CACHE") != "" { return nil } @@ -439,7 +310,7 @@ func (p *PodmanTest) RestoreAllArtifacts() error { // CreatePod creates a pod with no infra container // it optionally takes a pod name -func (p *PodmanTest) CreatePod(name string) (*PodmanSession, int, string) { +func (p *PodmanTestIntegration) CreatePod(name string) (*PodmanSessionIntegration, int, string) { var podmanArgs = []string{"pod", "create", "--infra=false", "--share", ""} if name != "" { podmanArgs = append(podmanArgs, "--name", name) @@ -451,7 +322,7 @@ func (p *PodmanTest) CreatePod(name string) (*PodmanSession, int, string) { //RunTopContainer runs a simple container in the background that // runs top. If the name passed != "", it will have a name -func (p *PodmanTest) RunTopContainer(name string) *PodmanSession { +func (p *PodmanTestIntegration) RunTopContainer(name string) *PodmanSessionIntegration { var podmanArgs = []string{"run"} if name != "" { podmanArgs = append(podmanArgs, "--name", name) @@ -460,7 +331,7 @@ func (p *PodmanTest) RunTopContainer(name string) *PodmanSession { return p.Podman(podmanArgs) } -func (p *PodmanTest) RunTopContainerInPod(name, pod string) *PodmanSession { +func (p *PodmanTestIntegration) RunTopContainerInPod(name, pod string) *PodmanSessionIntegration { var podmanArgs = []string{"run", "--pod", pod} if name != "" { podmanArgs = append(podmanArgs, "--name", name) @@ -471,7 +342,7 @@ func (p *PodmanTest) RunTopContainerInPod(name, pod string) *PodmanSession { //RunLsContainer runs a simple container in the background that // simply runs ls. If the name passed != "", it will have a name -func (p *PodmanTest) RunLsContainer(name string) (*PodmanSession, int, string) { +func (p *PodmanTestIntegration) RunLsContainer(name string) (*PodmanSessionIntegration, int, string) { var podmanArgs = []string{"run"} if name != "" { podmanArgs = append(podmanArgs, "--name", name) @@ -482,7 +353,7 @@ func (p *PodmanTest) RunLsContainer(name string) (*PodmanSession, int, string) { return session, session.ExitCode(), session.OutputToString() } -func (p *PodmanTest) RunLsContainerInPod(name, pod string) (*PodmanSession, int, string) { +func (p *PodmanTestIntegration) RunLsContainerInPod(name, pod string) (*PodmanSessionIntegration, int, string) { var podmanArgs = []string{"run", "--pod", pod} if name != "" { podmanArgs = append(podmanArgs, "--name", name) @@ -493,147 +364,9 @@ func (p *PodmanTest) RunLsContainerInPod(name, pod string) (*PodmanSession, int, return session, session.ExitCode(), session.OutputToString() } -//NumberOfContainersRunning returns an int of how many -// containers are currently running. -func (p *PodmanTest) NumberOfContainersRunning() int { - var containers []string - ps := p.Podman([]string{"ps", "-q"}) - ps.WaitWithDefaultTimeout() - Expect(ps.ExitCode()).To(Equal(0)) - for _, i := range ps.OutputToStringArray() { - if i != "" { - containers = append(containers, i) - } - } - return len(containers) -} - -// NumberOfContainers returns an int of how many -// containers are currently defined. -func (p *PodmanTest) NumberOfContainers() int { - var containers []string - ps := p.Podman([]string{"ps", "-aq"}) - ps.WaitWithDefaultTimeout() - Expect(ps.ExitCode()).To(Equal(0)) - for _, i := range ps.OutputToStringArray() { - if i != "" { - containers = append(containers, i) - } - } - return len(containers) -} - -// NumberOfPods returns an int of how many -// pods are currently defined. -func (p *PodmanTest) NumberOfPods() int { - var pods []string - ps := p.Podman([]string{"pod", "ps", "-q"}) - ps.WaitWithDefaultTimeout() - Expect(ps.ExitCode()).To(Equal(0)) - for _, i := range ps.OutputToStringArray() { - if i != "" { - pods = append(pods, i) - } - } - return len(pods) -} - -// NumberOfRunningContainers returns an int of how many containers are currently -// running -func (p *PodmanTest) NumberOfRunningContainers() int { - var containers []string - ps := p.Podman([]string{"ps", "-q"}) - ps.WaitWithDefaultTimeout() - Expect(ps.ExitCode()).To(Equal(0)) - for _, i := range ps.OutputToStringArray() { - if i != "" { - containers = append(containers, i) - } - } - return len(containers) -} - -// StringInSlice determines if a string is in a string slice, returns bool -func StringInSlice(s string, sl []string) bool { - for _, i := range sl { - if i == s { - return true - } - } - return false -} - -//LineInOutputStartsWith returns true if a line in a -// session output starts with the supplied string -func (s *PodmanSession) LineInOuputStartsWith(term string) bool { - for _, i := range s.OutputToStringArray() { - if strings.HasPrefix(i, term) { - return true - } - } - return false -} - -//LineInOutputContains returns true if a line in a -// session output starts with the supplied string -func (s *PodmanSession) LineInOutputContains(term string) bool { - for _, i := range s.OutputToStringArray() { - if strings.Contains(i, term) { - return true - } - } - return false -} - -//tagOutPutToMap parses each string in imagesOutput and returns -// a map of repo:tag pairs. Notice, the first array item will -// be skipped as it's considered to be the header. -func tagOutputToMap(imagesOutput []string) map[string]string { - m := make(map[string]string) - // iterate over output but skip the header - for _, i := range imagesOutput[1:] { - tmp := []string{} - for _, x := range strings.Split(i, " ") { - if x != "" { - tmp = append(tmp, x) - } - } - // podman-images(1) return a list like output - // in the format of "Repository Tag [...]" - if len(tmp) < 2 { - continue - } - m[tmp[0]] = tmp[1] - } - return m -} - -//LineInOutputContainsTag returns true if a line in the -// session's output contains the repo-tag pair as returned -// by podman-images(1). -func (s *PodmanSession) LineInOutputContainsTag(repo, tag string) bool { - tagMap := tagOutputToMap(s.OutputToStringArray()) - for r, t := range tagMap { - if repo == r && tag == t { - return true - } - } - return false -} - -//GetContainerStatus returns the containers state. -// This function assumes only one container is active. -func (p *PodmanTest) GetContainerStatus() string { - var podmanArgs = []string{"ps"} - podmanArgs = append(podmanArgs, "--all", "--format={{.Status}}") - session := p.Podman(podmanArgs) - session.WaitWithDefaultTimeout() - return session.OutputToString() -} - // BuildImage uses podman build and buildah to build an image // called imageName based on a string dockerfile -func (p *PodmanTest) BuildImage(dockerfile, imageName string, layers string) { +func (p *PodmanTestIntegration) BuildImage(dockerfile, imageName string, layers string) { dockerfilePath := filepath.Join(p.TempDir, "Dockerfile") err := ioutil.WriteFile(dockerfilePath, []byte(dockerfile), 0755) Expect(err).To(BeNil()) @@ -642,34 +375,12 @@ func (p *PodmanTest) BuildImage(dockerfile, imageName string, layers string) { Expect(session.ExitCode()).To(Equal(0)) } -//GetHostDistributionInfo returns a struct with its distribution name and version -func GetHostDistributionInfo() HostOS { - f, err := os.Open("/etc/os-release") - defer f.Close() - if err != nil { - return HostOS{} - } - - l := bufio.NewScanner(f) - host := HostOS{} - host.Arch = runtime.GOARCH - for l.Scan() { - if strings.HasPrefix(l.Text(), "ID=") { - host.Distribution = strings.Replace(strings.TrimSpace(strings.Join(strings.Split(l.Text(), "=")[1:], "")), "\"", "", -1) - } - if strings.HasPrefix(l.Text(), "VERSION_ID=") { - host.Version = strings.Replace(strings.TrimSpace(strings.Join(strings.Split(l.Text(), "=")[1:], "")), "\"", "", -1) - } - } - return host -} - -func (p *PodmanTest) setDefaultRegistriesConfigEnv() { +func (p *PodmanTestIntegration) setDefaultRegistriesConfigEnv() { defaultFile := filepath.Join(INTEGRATION_ROOT, "test/registries.conf") os.Setenv("REGISTRIES_CONFIG_PATH", defaultFile) } -func (p *PodmanTest) setRegistriesConfigEnv(b []byte) { +func (p *PodmanTestIntegration) setRegistriesConfigEnv(b []byte) { outfile := filepath.Join(p.TempDir, "registries.conf") os.Setenv("REGISTRIES_CONFIG_PATH", outfile) ioutil.WriteFile(outfile, b, 0644) @@ -678,81 +389,3 @@ func (p *PodmanTest) setRegistriesConfigEnv(b []byte) { func resetRegistriesConfigEnv() { os.Setenv("REGISTRIES_CONFIG_PATH", "") } - -// IsKernelNewThan compares the current kernel version to one provided. If -// the kernel is equal to or greater, returns true -func IsKernelNewThan(version string) (bool, error) { - inputVersion, err := kernel.ParseRelease(version) - if err != nil { - return false, err - } - kv, err := kernel.GetKernelVersion() - if err == nil { - return false, err - } - // CompareKernelVersion compares two kernel.VersionInfo structs. - // Returns -1 if a < b, 0 if a == b, 1 it a > b - result := kernel.CompareKernelVersion(*kv, *inputVersion) - if result >= 0 { - return true, nil - } - return false, nil - -} - -//Wait process or service inside container start, and ready to be used. -func WaitContainerReady(p *PodmanTest, id string, expStr string, timeout int, step int) bool { - startTime := time.Now() - s := p.Podman([]string{"logs", id}) - s.WaitWithDefaultTimeout() - fmt.Println(startTime) - for { - if time.Since(startTime) >= time.Duration(timeout)*time.Second { - return false - } - if strings.Contains(s.OutputToString(), expStr) { - return true - } - time.Sleep(time.Duration(step) * time.Second) - s = p.Podman([]string{"logs", id}) - s.WaitWithDefaultTimeout() - } -} - -//IsCommandAvaible check if command exist -func IsCommandAvailable(command string) bool { - check := exec.Command("bash", "-c", strings.Join([]string{"command -v", command}, " ")) - err := check.Run() - if err != nil { - return false - } - return true -} - -// WriteJsonFile write json format data to a json file -func WriteJsonFile(data []byte, filePath string) error { - var jsonData map[string]interface{} - json.Unmarshal(data, &jsonData) - formatJson, _ := json.MarshalIndent(jsonData, "", " ") - return ioutil.WriteFile(filePath, formatJson, 0644) -} - -func getTestContext() context.Context { - return context.Background() -} - -func containerized() bool { - container := os.Getenv("container") - if container != "" { - return true - } - b, err := ioutil.ReadFile("/proc/1/cgroup") - if err != nil { - // shrug, if we cannot read that file, return false - return false - } - if strings.Index(string(b), "docker") > -1 { - return true - } - return false -} |