github.com/containers/podman/v5@v5.1.0-rc1/test/e2e/libpod_suite_remote_test.go (about) 1 //go:build remote_testing 2 3 package integration 4 5 import ( 6 "errors" 7 "fmt" 8 "net" 9 "os" 10 "os/exec" 11 "path/filepath" 12 "strings" 13 "syscall" 14 "time" 15 16 . "github.com/onsi/ginkgo/v2" 17 . "github.com/onsi/gomega" 18 ) 19 20 func IsRemote() bool { 21 return true 22 } 23 24 // Podman is the exec call to podman on the filesystem 25 func (p *PodmanTestIntegration) Podman(args []string) *PodmanSessionIntegration { 26 args = p.makeOptions(args, false, false) 27 podmanSession := p.PodmanBase(args, false, false) 28 return &PodmanSessionIntegration{podmanSession} 29 } 30 31 // PodmanSystemdScope runs the podman command in a new systemd scope 32 func (p *PodmanTestIntegration) PodmanSystemdScope(args []string) *PodmanSessionIntegration { 33 args = p.makeOptions(args, false, false) 34 35 wrapper := []string{"systemd-run", "--scope"} 36 if isRootless() { 37 wrapper = []string{"systemd-run", "--scope", "--user"} 38 } 39 40 podmanSession := p.PodmanAsUserBase(args, 0, 0, "", nil, false, false, wrapper, nil) 41 return &PodmanSessionIntegration{podmanSession} 42 } 43 44 // PodmanExtraFiles is the exec call to podman on the filesystem and passes down extra files 45 func (p *PodmanTestIntegration) PodmanExtraFiles(args []string, extraFiles []*os.File) *PodmanSessionIntegration { 46 args = p.makeOptions(args, false, false) 47 podmanSession := p.PodmanAsUserBase(args, 0, 0, "", nil, false, false, nil, extraFiles) 48 return &PodmanSessionIntegration{podmanSession} 49 } 50 51 func (p *PodmanTestIntegration) setDefaultRegistriesConfigEnv() { 52 defaultFile := filepath.Join(INTEGRATION_ROOT, "test/registries.conf") 53 os.Setenv("CONTAINERS_REGISTRIES_CONF", defaultFile) 54 } 55 56 func (p *PodmanTestIntegration) setRegistriesConfigEnv(b []byte) { 57 outfile := filepath.Join(p.TempDir, "registries.conf") 58 os.Setenv("CONTAINERS_REGISTRIES_CONF", outfile) 59 err := os.WriteFile(outfile, b, 0644) 60 Expect(err).ToNot(HaveOccurred()) 61 } 62 63 func resetRegistriesConfigEnv() { 64 os.Setenv("CONTAINERS_REGISTRIES_CONF", "") 65 } 66 func PodmanTestCreate(tempDir string) *PodmanTestIntegration { 67 pti := PodmanTestCreateUtil(tempDir, true) 68 pti.StartRemoteService() 69 return pti 70 } 71 72 func (p *PodmanTestIntegration) StartRemoteService() { 73 if !isRootless() { 74 err := os.MkdirAll("/run/podman", 0755) 75 Expect(err).ToNot(HaveOccurred()) 76 } 77 78 args := []string{} 79 if _, found := os.LookupEnv("DEBUG_SERVICE"); found { 80 args = append(args, "--log-level", "trace") 81 } 82 remoteSocket := p.RemoteSocket 83 args = append(args, "system", "service", "--time", "0", remoteSocket) 84 podmanOptions := getRemoteOptions(p, args) 85 cacheOptions := []string{"--storage-opt", 86 fmt.Sprintf("%s.imagestore=%s", p.PodmanTest.ImageCacheFS, p.PodmanTest.ImageCacheDir)} 87 podmanOptions = append(cacheOptions, podmanOptions...) 88 command := exec.Command(p.PodmanBinary, podmanOptions...) 89 command.Stdout = GinkgoWriter 90 command.Stderr = GinkgoWriter 91 GinkgoWriter.Printf("Running: %s %s\n", p.PodmanBinary, strings.Join(podmanOptions, " ")) 92 err := command.Start() 93 Expect(err).ToNot(HaveOccurred()) 94 command.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} 95 p.RemoteCommand = command 96 p.RemoteSession = command.Process 97 err = p.DelayForService() 98 Expect(err).ToNot(HaveOccurred()) 99 } 100 101 func (p *PodmanTestIntegration) StopRemoteService() { 102 if err := p.RemoteSession.Kill(); err != nil { 103 GinkgoWriter.Printf("unable to clean up service %d, %v\n", p.RemoteSession.Pid, err) 104 } 105 if _, err := p.RemoteSession.Wait(); err != nil { 106 GinkgoWriter.Printf("error on remote stop-wait %q", err) 107 } 108 socket := strings.Split(p.RemoteSocket, ":")[1] 109 if err := os.Remove(socket); err != nil && !errors.Is(err, os.ErrNotExist) { 110 GinkgoWriter.Printf("%v\n", err) 111 } 112 if p.RemoteSocketLock != "" { 113 if err := os.Remove(p.RemoteSocketLock); err != nil && !errors.Is(err, os.ErrNotExist) { 114 GinkgoWriter.Printf("%v\n", err) 115 } 116 } 117 } 118 119 // getRemoteOptions assembles all the podman main options 120 func getRemoteOptions(p *PodmanTestIntegration, args []string) []string { 121 networkDir := p.NetworkConfigDir 122 podmanOptions := strings.Split(fmt.Sprintf("--root %s --runroot %s --runtime %s --conmon %s --network-config-dir %s --network-backend %s --cgroup-manager %s --tmpdir %s --events-backend %s --db-backend %s", 123 p.Root, p.RunRoot, p.OCIRuntime, p.ConmonBinary, networkDir, p.NetworkBackend.ToString(), p.CgroupManager, p.TmpDir, "file", p.DatabaseBackend), " ") 124 podmanOptions = append(podmanOptions, strings.Split(p.StorageOptions, " ")...) 125 podmanOptions = append(podmanOptions, args...) 126 return podmanOptions 127 } 128 129 // RestoreArtifact puts the cached image into our test store 130 func (p *PodmanTestIntegration) RestoreArtifact(image string) error { 131 tarball := imageTarPath(image) 132 if _, err := os.Stat(tarball); err == nil { 133 GinkgoWriter.Printf("Restoring %s...\n", image) 134 args := []string{"load", "-q", "-i", tarball} 135 podmanOptions := getRemoteOptions(p, args) 136 command := exec.Command(p.PodmanBinary, podmanOptions...) 137 GinkgoWriter.Printf("Running: %s %s\n", p.PodmanBinary, strings.Join(podmanOptions, " ")) 138 if err := command.Start(); err != nil { 139 return err 140 } 141 if err := command.Wait(); err != nil { 142 return err 143 } 144 } 145 return nil 146 } 147 148 func (p *PodmanTestIntegration) DelayForService() error { 149 var err error 150 var conn net.Conn 151 for i := 0; i < 100; i++ { 152 conn, err = net.Dial("unix", strings.TrimPrefix(p.RemoteSocket, "unix:")) 153 if err == nil { 154 conn.Close() 155 return nil 156 } 157 time.Sleep(100 * time.Millisecond) 158 } 159 return fmt.Errorf("service socket not detected, timeout after 10 seconds: %w", err) 160 }