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 }