github.com/hanks177/podman/v4@v4.1.3-0.20220613032544-16d90015bc83/pkg/bindings/test/common_test.go (about)

     1  package bindings_test
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"os"
     8  	"os/exec"
     9  	"path/filepath"
    10  	"strings"
    11  	"time"
    12  
    13  	"github.com/hanks177/podman/v4/libpod/define"
    14  	. "github.com/hanks177/podman/v4/pkg/bindings"
    15  	"github.com/hanks177/podman/v4/pkg/bindings/containers"
    16  	"github.com/hanks177/podman/v4/pkg/specgen"
    17  	"github.com/onsi/ginkgo"
    18  	"github.com/onsi/gomega/gexec"
    19  	"github.com/pkg/errors"
    20  )
    21  
    22  type testImage struct {
    23  	name        string
    24  	shortName   string
    25  	tarballName string
    26  }
    27  
    28  const (
    29  	devPodmanBinaryLocation     string = "../../../bin/podman"
    30  	defaultPodmanBinaryLocation string = "/usr/bin/podman"
    31  )
    32  
    33  func getPodmanBinary() string {
    34  	_, err := os.Stat(devPodmanBinaryLocation)
    35  	if os.IsNotExist(err) {
    36  		return defaultPodmanBinaryLocation
    37  	}
    38  	return devPodmanBinaryLocation
    39  }
    40  
    41  var (
    42  	ImageCacheDir = "/tmp/podman/imagecachedir"
    43  	LockTmpDir    string
    44  	alpine        = testImage{
    45  		name:        "docker.io/library/alpine:latest",
    46  		shortName:   "alpine",
    47  		tarballName: "alpine.tar",
    48  	}
    49  	busybox = testImage{
    50  		name:        "docker.io/library/busybox:latest",
    51  		shortName:   "busybox",
    52  		tarballName: "busybox.tar",
    53  	}
    54  	CACHE_IMAGES = []testImage{alpine, busybox} //nolint:revive,stylecheck
    55  )
    56  
    57  type bindingTest struct {
    58  	artifactDirPath string
    59  	imageCacheDir   string
    60  	sock            string
    61  	tempDirPath     string
    62  	runRoot         string
    63  	crioRoot        string
    64  	conn            context.Context
    65  }
    66  
    67  func (b *bindingTest) NewConnection() error {
    68  	connText, err := NewConnection(context.Background(), b.sock)
    69  	if err != nil {
    70  		return err
    71  	}
    72  	b.conn = connText
    73  	return nil
    74  }
    75  
    76  func (b *bindingTest) runPodman(command []string) *gexec.Session {
    77  	var cmd []string
    78  	podmanBinary := getPodmanBinary()
    79  	val, ok := os.LookupEnv("PODMAN_BINARY")
    80  	if ok {
    81  		podmanBinary = val
    82  	}
    83  	val, ok = os.LookupEnv("CGROUP_MANAGER")
    84  	if ok {
    85  		cmd = append(cmd, "--cgroup-manager", val)
    86  	}
    87  	val, ok = os.LookupEnv("CNI_CONFIG_DIR")
    88  	if ok {
    89  		cmd = append(cmd, "--network-config-dir", val)
    90  	}
    91  	val, ok = os.LookupEnv("CONMON")
    92  	if ok {
    93  		cmd = append(cmd, "--conmon", val)
    94  	}
    95  	val, ok = os.LookupEnv("ROOT")
    96  	if ok {
    97  		cmd = append(cmd, "--root", val)
    98  	} else {
    99  		cmd = append(cmd, "--root", b.crioRoot)
   100  	}
   101  	val, ok = os.LookupEnv("OCI_RUNTIME")
   102  	if ok {
   103  		cmd = append(cmd, "--runtime", val)
   104  	}
   105  	val, ok = os.LookupEnv("RUNROOT")
   106  	if ok {
   107  		cmd = append(cmd, "--runroot", val)
   108  	} else {
   109  		cmd = append(cmd, "--runroot", b.runRoot)
   110  	}
   111  	val, ok = os.LookupEnv("TEMPDIR")
   112  	if ok {
   113  		cmd = append(cmd, "--tmpdir", val)
   114  	} else {
   115  		cmd = append(cmd, "--tmpdir", b.tempDirPath)
   116  	}
   117  	val, ok = os.LookupEnv("STORAGE_DRIVER")
   118  	if ok {
   119  		cmd = append(cmd, "--storage-driver", val)
   120  	}
   121  	val, ok = os.LookupEnv("STORAGE_OPTIONS")
   122  	if ok {
   123  		cmd = append(cmd, "--storage", val)
   124  	}
   125  	cmd = append(cmd, command...)
   126  	c := exec.Command(podmanBinary, cmd...)
   127  	fmt.Printf("Running: %s %s\n", podmanBinary, strings.Join(cmd, " "))
   128  	session, err := gexec.Start(c, ginkgo.GinkgoWriter, ginkgo.GinkgoWriter)
   129  	if err != nil {
   130  		panic(errors.Errorf("unable to run podman command: %q", cmd))
   131  	}
   132  	return session
   133  }
   134  
   135  func newBindingTest() *bindingTest {
   136  	tmpPath, _ := createTempDirInTempDir()
   137  	b := bindingTest{
   138  		crioRoot:        filepath.Join(tmpPath, "crio"),
   139  		runRoot:         filepath.Join(tmpPath, "run"),
   140  		artifactDirPath: "",
   141  		imageCacheDir:   "",
   142  		sock:            fmt.Sprintf("unix://%s", filepath.Join(tmpPath, "api.sock")),
   143  		tempDirPath:     tmpPath,
   144  	}
   145  	return &b
   146  }
   147  
   148  // createTempDirinTempDir create a temp dir with prefix podman_test
   149  func createTempDirInTempDir() (string, error) {
   150  	return ioutil.TempDir("", "libpod_api")
   151  }
   152  
   153  func (b *bindingTest) startAPIService() *gexec.Session {
   154  	cmd := []string{"--log-level=debug", "system", "service", "--timeout=0", b.sock}
   155  	session := b.runPodman(cmd)
   156  
   157  	sock := strings.TrimPrefix(b.sock, "unix://")
   158  	for i := 0; i < 10; i++ {
   159  		if _, err := os.Stat(sock); err != nil {
   160  			if !os.IsNotExist(err) {
   161  				break
   162  			}
   163  			time.Sleep(time.Second)
   164  			continue
   165  		}
   166  		break
   167  	}
   168  	return session
   169  }
   170  
   171  func (b *bindingTest) cleanup() {
   172  	s := b.runPodman([]string{"stop", "-a", "-t", "0"})
   173  	s.Wait(45)
   174  	if err := os.RemoveAll(b.tempDirPath); err != nil {
   175  		fmt.Println(err)
   176  	}
   177  }
   178  
   179  // Pull is a helper function to pull in images
   180  func (b *bindingTest) Pull(name string) {
   181  	p := b.runPodman([]string{"pull", name})
   182  	p.Wait(45)
   183  }
   184  
   185  func (b *bindingTest) Save(i testImage) {
   186  	p := b.runPodman([]string{"save", "-o", filepath.Join(ImageCacheDir, i.tarballName), i.name})
   187  	p.Wait(45)
   188  }
   189  
   190  func (b *bindingTest) RestoreImagesFromCache() {
   191  	for _, i := range CACHE_IMAGES {
   192  		b.restoreImageFromCache(i)
   193  	}
   194  }
   195  func (b *bindingTest) restoreImageFromCache(i testImage) {
   196  	p := b.runPodman([]string{"load", "-i", filepath.Join(ImageCacheDir, i.tarballName)})
   197  	p.Wait(45)
   198  }
   199  
   200  // Run a container within or without a pod
   201  // and add or append the alpine image to it
   202  func (b *bindingTest) RunTopContainer(containerName *string, podName *string) (string, error) {
   203  	s := specgen.NewSpecGenerator(alpine.name, false)
   204  	s.Terminal = false
   205  	s.Command = []string{"/usr/bin/top"}
   206  	if containerName != nil {
   207  		s.Name = *containerName
   208  	}
   209  	if podName != nil {
   210  		s.Pod = *podName
   211  	}
   212  	ctr, err := containers.CreateWithSpec(b.conn, s, nil)
   213  	if err != nil {
   214  		return "", err
   215  	}
   216  	err = containers.Start(b.conn, ctr.ID, nil)
   217  	if err != nil {
   218  		return "", err
   219  	}
   220  	wait := define.ContainerStateRunning
   221  	_, err = containers.Wait(b.conn, ctr.ID, new(containers.WaitOptions).WithCondition([]define.ContainerStatus{wait}))
   222  	return ctr.ID, err
   223  }
   224  
   225  // This method creates a pod with the given pod name.
   226  // Podname is an optional parameter
   227  func (b *bindingTest) Podcreate(name *string) {
   228  	b.PodcreateAndExpose(name, nil)
   229  }
   230  
   231  // This method creates a pod with the given pod name and publish port.
   232  // Podname is an optional parameter
   233  // port is an optional parameter
   234  func (b *bindingTest) PodcreateAndExpose(name *string, port *string) {
   235  	command := []string{"pod", "create"}
   236  	if name != nil {
   237  		podname := *name
   238  		command = append(command, "--name", podname)
   239  	}
   240  	if port != nil {
   241  		podport := *port
   242  		command = append(command, "--publish", podport)
   243  	}
   244  	b.runPodman(command).Wait(45)
   245  }
   246  
   247  //  StringInSlice returns a boolean based on whether a given
   248  //  string is in a given slice
   249  func StringInSlice(s string, sl []string) bool {
   250  	for _, val := range sl {
   251  		if s == val {
   252  			return true
   253  		}
   254  	}
   255  	return false
   256  }
   257  
   258  var _ = ginkgo.SynchronizedBeforeSuite(func() []byte {
   259  	// make cache dir
   260  	if err := os.MkdirAll(ImageCacheDir, 0777); err != nil {
   261  		fmt.Printf("%q\n", err)
   262  		os.Exit(1)
   263  	}
   264  
   265  	// If running localized tests, the cache dir is created and populated. if the
   266  	// tests are remote, this is a no-op
   267  	createCache()
   268  	path, err := ioutil.TempDir("", "libpodlock")
   269  	if err != nil {
   270  		fmt.Println(err)
   271  		os.Exit(1)
   272  	}
   273  	return []byte(path)
   274  }, func(data []byte) {
   275  	LockTmpDir = string(data)
   276  })
   277  
   278  func createCache() {
   279  	b := newBindingTest()
   280  	for _, i := range CACHE_IMAGES {
   281  		_, err := os.Stat(filepath.Join(ImageCacheDir, i.tarballName))
   282  		if os.IsNotExist(err) {
   283  			//	pull the image
   284  			b.Pull(i.name)
   285  			b.Save(i)
   286  		}
   287  	}
   288  	b.cleanup()
   289  }
   290  
   291  func isStopped(state string) bool {
   292  	return state == "exited" || state == "stopped"
   293  }