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