podman/test/e2e/libpod_suite_remote_test.go

161 lines
5.3 KiB
Go

//go:build remote_testing
package integration
import (
"errors"
"fmt"
"net"
"os"
"os/exec"
"path/filepath"
"strings"
"syscall"
"time"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
func IsRemote() bool {
return true
}
// Podman is the exec call to podman on the filesystem
func (p *PodmanTestIntegration) Podman(args []string) *PodmanSessionIntegration {
args = p.makeOptions(args, false, false)
podmanSession := p.PodmanBase(args, false, false)
return &PodmanSessionIntegration{podmanSession}
}
// PodmanSystemdScope runs the podman command in a new systemd scope
func (p *PodmanTestIntegration) PodmanSystemdScope(args []string) *PodmanSessionIntegration {
args = p.makeOptions(args, false, false)
wrapper := []string{"systemd-run", "--scope"}
if isRootless() {
wrapper = []string{"systemd-run", "--scope", "--user"}
}
podmanSession := p.PodmanAsUserBase(args, 0, 0, "", nil, false, false, wrapper, nil)
return &PodmanSessionIntegration{podmanSession}
}
// PodmanExtraFiles is the exec call to podman on the filesystem and passes down extra files
func (p *PodmanTestIntegration) PodmanExtraFiles(args []string, extraFiles []*os.File) *PodmanSessionIntegration {
args = p.makeOptions(args, false, false)
podmanSession := p.PodmanAsUserBase(args, 0, 0, "", nil, false, false, nil, extraFiles)
return &PodmanSessionIntegration{podmanSession}
}
func (p *PodmanTestIntegration) setDefaultRegistriesConfigEnv() {
defaultFile := filepath.Join(INTEGRATION_ROOT, "test/registries.conf")
os.Setenv("CONTAINERS_REGISTRIES_CONF", defaultFile)
}
func (p *PodmanTestIntegration) setRegistriesConfigEnv(b []byte) {
outfile := filepath.Join(p.TempDir, "registries.conf")
os.Setenv("CONTAINERS_REGISTRIES_CONF", outfile)
err := os.WriteFile(outfile, b, 0644)
Expect(err).ToNot(HaveOccurred())
}
func resetRegistriesConfigEnv() {
os.Setenv("CONTAINERS_REGISTRIES_CONF", "")
}
func PodmanTestCreate(tempDir string) *PodmanTestIntegration {
pti := PodmanTestCreateUtil(tempDir, true)
pti.StartRemoteService()
return pti
}
func (p *PodmanTestIntegration) StartRemoteService() {
if !isRootless() {
err := os.MkdirAll("/run/podman", 0755)
Expect(err).ToNot(HaveOccurred())
}
args := []string{}
if _, found := os.LookupEnv("DEBUG_SERVICE"); found {
args = append(args, "--log-level", "trace")
}
remoteSocket := p.RemoteSocket
args = append(args, "system", "service", "--time", "0", remoteSocket)
podmanOptions := getRemoteOptions(p, args)
cacheOptions := []string{"--storage-opt",
fmt.Sprintf("%s.imagestore=%s", p.PodmanTest.ImageCacheFS, p.PodmanTest.ImageCacheDir)}
podmanOptions = append(cacheOptions, podmanOptions...)
command := exec.Command(p.PodmanBinary, podmanOptions...)
command.Stdout = GinkgoWriter
command.Stderr = GinkgoWriter
GinkgoWriter.Printf("Running: %s %s\n", p.PodmanBinary, strings.Join(podmanOptions, " "))
err := command.Start()
Expect(err).ToNot(HaveOccurred())
command.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
p.RemoteCommand = command
p.RemoteSession = command.Process
err = p.DelayForService()
Expect(err).ToNot(HaveOccurred())
}
func (p *PodmanTestIntegration) StopRemoteService() {
if err := p.RemoteSession.Kill(); err != nil {
GinkgoWriter.Printf("unable to clean up service %d, %v\n", p.RemoteSession.Pid, err)
}
if _, err := p.RemoteSession.Wait(); err != nil {
GinkgoWriter.Printf("error on remote stop-wait %q", err)
}
socket := strings.Split(p.RemoteSocket, ":")[1]
if err := os.Remove(socket); err != nil && !errors.Is(err, os.ErrNotExist) {
GinkgoWriter.Printf("%v\n", err)
}
if p.RemoteSocketLock != "" {
if err := os.Remove(p.RemoteSocketLock); err != nil && !errors.Is(err, os.ErrNotExist) {
GinkgoWriter.Printf("%v\n", err)
}
}
}
// getRemoteOptions assembles all the podman main options
func getRemoteOptions(p *PodmanTestIntegration, args []string) []string {
networkDir := p.NetworkConfigDir
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",
p.Root, p.RunRoot, p.OCIRuntime, p.ConmonBinary, networkDir, p.NetworkBackend.ToString(), p.CgroupManager, p.TmpDir, "file", p.DatabaseBackend), " ")
podmanOptions = append(podmanOptions, strings.Split(p.StorageOptions, " ")...)
podmanOptions = append(podmanOptions, args...)
return podmanOptions
}
// RestoreArtifact puts the cached image into our test store
func (p *PodmanTestIntegration) RestoreArtifact(image string) error {
tarball := imageTarPath(image)
if _, err := os.Stat(tarball); err == nil {
GinkgoWriter.Printf("Restoring %s...\n", image)
args := []string{"load", "-q", "-i", tarball}
podmanOptions := getRemoteOptions(p, args)
command := exec.Command(p.PodmanBinary, podmanOptions...)
GinkgoWriter.Printf("Running: %s %s\n", p.PodmanBinary, strings.Join(podmanOptions, " "))
if err := command.Start(); err != nil {
return err
}
if err := command.Wait(); err != nil {
return err
}
}
return nil
}
func (p *PodmanTestIntegration) DelayForService() error {
var err error
var conn net.Conn
for i := 0; i < 100; i++ {
conn, err = net.Dial("unix", strings.TrimPrefix(p.RemoteSocket, "unix:"))
if err == nil {
conn.Close()
return nil
}
time.Sleep(100 * time.Millisecond)
}
return fmt.Errorf("service socket not detected, timeout after 10 seconds: %w", err)
}