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