github.com/containers/podman/v4@v4.9.4/pkg/bindings/test/common_test.go (about) 1 package bindings_test 2 3 import ( 4 "context" 5 "fmt" 6 "os" 7 "os/exec" 8 "path/filepath" 9 "strings" 10 "time" 11 12 "github.com/containers/podman/v4/libpod/define" 13 . "github.com/containers/podman/v4/pkg/bindings" 14 "github.com/containers/podman/v4/pkg/bindings/containers" 15 "github.com/containers/podman/v4/pkg/specgen" 16 "github.com/onsi/ginkgo/v2" 17 . "github.com/onsi/gomega" 18 . "github.com/onsi/gomega/gexec" 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} //nolint:revive,stylecheck 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) *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, "--network-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 := Start(c, ginkgo.GinkgoWriter, ginkgo.GinkgoWriter) 128 if err != nil { 129 panic(fmt.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 os.MkdirTemp("", "libpod_api") 150 } 151 152 func (b *bindingTest) startAPIService() *Session { 153 cmd := []string{"--log-level=debug", "system", "service", "--timeout=0", b.sock} 154 session := b.runPodman(cmd) 155 156 sock := strings.TrimPrefix(b.sock, "unix://") 157 for i := 0; i < 10; i++ { 158 if _, err := os.Stat(sock); err != nil { 159 if !os.IsNotExist(err) { 160 break 161 } 162 time.Sleep(time.Second) 163 continue 164 } 165 break 166 } 167 return session 168 } 169 170 func (b *bindingTest) cleanup() { 171 s := b.runPodman([]string{"stop", "-a", "-t", "0"}) 172 s.Wait(45) 173 if err := os.RemoveAll(b.tempDirPath); err != nil { 174 fmt.Println(err) 175 } 176 } 177 178 // Pull is a helper function to pull in images 179 func (b *bindingTest) Pull(name string) { 180 p := b.runPodman([]string{"pull", name}) 181 p.Wait(45) 182 Expect(p).To(Exit(0)) 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 Expect(p).To(Exit(0)) 189 } 190 191 func (b *bindingTest) RestoreImagesFromCache() { 192 for _, i := range CACHE_IMAGES { 193 b.restoreImageFromCache(i) 194 } 195 } 196 func (b *bindingTest) restoreImageFromCache(i testImage) { 197 p := b.runPodman([]string{"load", "-i", filepath.Join(ImageCacheDir, i.tarballName)}) 198 p.Wait(45) 199 Expect(p).To(Exit(0)) 200 } 201 202 // Run a container within or without a pod 203 // and add or append the alpine image to it 204 func (b *bindingTest) RunTopContainer(containerName *string, podName *string) (string, error) { 205 s := specgen.NewSpecGenerator(alpine.name, false) 206 s.Terminal = false 207 s.Command = []string{"/usr/bin/top"} 208 if containerName != nil { 209 s.Name = *containerName 210 } 211 if podName != nil { 212 s.Pod = *podName 213 } 214 ctr, err := containers.CreateWithSpec(b.conn, s, nil) 215 if err != nil { 216 return "", err 217 } 218 err = containers.Start(b.conn, ctr.ID, nil) 219 if err != nil { 220 return "", err 221 } 222 wait := define.ContainerStateRunning 223 _, err = containers.Wait(b.conn, ctr.ID, new(containers.WaitOptions).WithCondition([]define.ContainerStatus{wait})) 224 return ctr.ID, err 225 } 226 227 // This method creates a pod with the given pod name. 228 // Podname is an optional parameter 229 func (b *bindingTest) Podcreate(name *string) { 230 b.PodcreateAndExpose(name, nil) 231 } 232 233 // This method creates a pod with the given pod name and publish port. 234 // Podname is an optional parameter 235 // port is an optional parameter 236 func (b *bindingTest) PodcreateAndExpose(name *string, port *string) { 237 command := []string{"pod", "create"} 238 if name != nil { 239 podname := *name 240 command = append(command, "--name", podname) 241 } 242 if port != nil { 243 podport := *port 244 command = append(command, "--publish", podport) 245 } 246 b.runPodman(command).Wait(45) 247 } 248 249 // StringInSlice returns a boolean based on whether a given 250 // string is in a given slice 251 func StringInSlice(s string, sl []string) bool { 252 for _, val := range sl { 253 if s == val { 254 return true 255 } 256 } 257 return false 258 } 259 260 var _ = ginkgo.SynchronizedBeforeSuite(func() []byte { 261 // make cache dir 262 err := os.MkdirAll(ImageCacheDir, 0777) 263 Expect(err).ToNot(HaveOccurred()) 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 := os.MkdirTemp("", "libpodlock") 269 Expect(err).ToNot(HaveOccurred()) 270 271 return []byte(path) 272 }, func(data []byte) { 273 LockTmpDir = string(data) 274 }) 275 276 func createCache() { 277 b := newBindingTest() 278 for _, i := range CACHE_IMAGES { 279 _, err := os.Stat(filepath.Join(ImageCacheDir, i.tarballName)) 280 if os.IsNotExist(err) { 281 // pull the image 282 b.Pull(i.name) 283 b.Save(i) 284 } 285 } 286 b.cleanup() 287 } 288 289 func isStopped(state string) bool { 290 return state == "exited" || state == "stopped" 291 }