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  }