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  }