1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
|
//go:build remote_testing && (linux || freebsd)
package integration
import (
"errors"
"fmt"
"net"
"os"
"os/exec"
"path/filepath"
"strings"
"syscall"
"time"
. "github.com/containers/podman/v5/test/utils"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
var RemoteTestingTarget = PodmanTestCreateUtilTarget(os.Getenv("REMOTEINTEGRATION_TRANSPORT"))
func IsRemote() bool {
return true
}
// Podman executes podman on the filesystem with default options.
func (p *PodmanTestIntegration) Podman(args []string) *PodmanSessionIntegration {
return p.PodmanWithOptions(PodmanExecOptions{}, args...)
}
// PodmanWithOptions executes podman on the filesystem with the supplied options.
func (p *PodmanTestIntegration) PodmanWithOptions(options PodmanExecOptions, args ...string) *PodmanSessionIntegration {
args = p.makeOptions(args, options)
podmanSession := p.PodmanExecBaseWithOptions(args, options)
return &PodmanSessionIntegration{podmanSession}
}
func (p *PodmanTestIntegration) setDefaultRegistriesConfigEnv() {
defaultFile := "registries.conf"
if UsingCacheRegistry() {
defaultFile = "registries-cached.conf"
}
defaultPath := filepath.Join(INTEGRATION_ROOT, "test", defaultFile)
os.Setenv("CONTAINERS_REGISTRIES_CONF", defaultPath)
}
func (p *PodmanTestIntegration) setRegistriesConfigEnv(b []byte) {
outfile := filepath.Join(p.TempDir, "registries.conf")
os.Setenv("CONTAINERS_REGISTRIES_CONF", outfile)
err := os.WriteFile(outfile, b, 0o644)
Expect(err).ToNot(HaveOccurred())
}
func resetRegistriesConfigEnv() {
os.Setenv("CONTAINERS_REGISTRIES_CONF", "")
}
func (p *PodmanTestIntegration) StartRemoteService() {
if !isRootless() {
err := os.MkdirAll("/run/podman", 0o755)
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")
if p.RemoteTLSClientCAFile != "" {
args = append(args, "--tls-client-ca", p.RemoteTLSClientCAFile)
}
if p.RemoteTLSServerCertFile != "" {
args = append(args, "--tls-cert", p.RemoteTLSServerCertFile)
}
if p.RemoteTLSServerKeyFile != "" {
args = append(args, "--tls-key", p.RemoteTLSServerKeyFile)
}
args = append(args, 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.Signal(syscall.SIGTERM); 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
}
func PodmanTestCreate(tempDir string) *PodmanTestIntegration {
pti := PodmanTestCreateUtil(tempDir, RemoteTestingTarget)
pti.StartRemoteService()
return pti
}
// 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(p.RemoteSocketScheme, strings.TrimPrefix(p.RemoteSocket, p.RemoteSocketScheme+"://"))
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)
}
|