github.com/hanks177/podman/v4@v4.1.3-0.20220613032544-16d90015bc83/pkg/machine/e2e/config.go (about)

     1  package e2e
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"math/rand"
     7  	"os"
     8  	"os/exec"
     9  	"path/filepath"
    10  	"strings"
    11  	"time"
    12  
    13  	"github.com/hanks177/podman/v4/pkg/machine"
    14  	"github.com/hanks177/podman/v4/pkg/machine/qemu"
    15  	"github.com/hanks177/podman/v4/pkg/util"
    16  	. "github.com/onsi/ginkgo" //nolint:golint,stylecheck
    17  	. "github.com/onsi/gomega"
    18  	"github.com/onsi/gomega/gexec"
    19  	. "github.com/onsi/gomega/gexec" //nolint:golint,stylecheck
    20  )
    21  
    22  var originalHomeDir = os.Getenv("HOME")
    23  
    24  const (
    25  	defaultTimeout time.Duration = 90 * time.Second
    26  )
    27  
    28  type machineCommand interface {
    29  	buildCmd(m *machineTestBuilder) []string
    30  }
    31  
    32  type MachineTestBuilder interface {
    33  	setName(string) *MachineTestBuilder
    34  	setCmd(mc machineCommand) *MachineTestBuilder
    35  	setTimeout(duration time.Duration) *MachineTestBuilder
    36  	run() (*machineSession, error)
    37  }
    38  type machineSession struct {
    39  	*gexec.Session
    40  }
    41  
    42  type machineTestBuilder struct {
    43  	cmd          []string
    44  	imagePath    string
    45  	name         string
    46  	names        []string
    47  	podmanBinary string
    48  	timeout      time.Duration
    49  }
    50  type qemuMachineInspectInfo struct {
    51  	State machine.Status
    52  	VM    qemu.MachineVM
    53  }
    54  
    55  // waitWithTimeout waits for a command to complete for a given
    56  // number of seconds
    57  func (ms *machineSession) waitWithTimeout(timeout time.Duration) {
    58  	Eventually(ms, timeout).Should(Exit())
    59  	os.Stdout.Sync()
    60  	os.Stderr.Sync()
    61  }
    62  
    63  func (ms *machineSession) Bytes() []byte {
    64  	return []byte(ms.outputToString())
    65  }
    66  
    67  func (ms *machineSession) outputToStringSlice() []string {
    68  	var results []string
    69  	output := string(ms.Out.Contents())
    70  	for _, line := range strings.Split(output, "\n") {
    71  		if line != "" {
    72  			results = append(results, line)
    73  		}
    74  	}
    75  	return results
    76  }
    77  
    78  // outputToString returns the output from a session in string form
    79  func (ms *machineSession) outputToString() string {
    80  	if ms == nil || ms.Out == nil || ms.Out.Contents() == nil {
    81  		return ""
    82  	}
    83  
    84  	fields := strings.Fields(string(ms.Out.Contents()))
    85  	return strings.Join(fields, " ")
    86  }
    87  
    88  // errorToString returns the error output from a session in string form
    89  func (ms *machineSession) errorToString() string {
    90  	if ms == nil || ms.Err == nil || ms.Err.Contents() == nil {
    91  		return ""
    92  	}
    93  	return string(ms.Err.Contents())
    94  }
    95  
    96  // newMB constructor for machine test builders
    97  func newMB() (*machineTestBuilder, error) {
    98  	mb := machineTestBuilder{
    99  		timeout: defaultTimeout,
   100  	}
   101  	cwd, err := os.Getwd()
   102  	if err != nil {
   103  		return nil, err
   104  	}
   105  	mb.podmanBinary = filepath.Join(cwd, "../../../bin/podman-remote")
   106  	if os.Getenv("PODMAN_BINARY") != "" {
   107  		mb.podmanBinary = os.Getenv("PODMAN_BINARY")
   108  	}
   109  	return &mb, nil
   110  }
   111  
   112  // setName sets the name of the virtuaql machine for the command
   113  func (m *machineTestBuilder) setName(name string) *machineTestBuilder {
   114  	m.name = name
   115  	return m
   116  }
   117  
   118  // setCmd takes a machineCommand struct and assembles a cmd line
   119  // representation of the podman machine command
   120  func (m *machineTestBuilder) setCmd(mc machineCommand) *machineTestBuilder {
   121  	// If no name for the machine exists, we set a random name.
   122  	if !util.StringInSlice(m.name, m.names) {
   123  		if len(m.name) < 1 {
   124  			m.name = randomString(12)
   125  		}
   126  		m.names = append(m.names, m.name)
   127  	}
   128  	m.cmd = mc.buildCmd(m)
   129  	return m
   130  }
   131  
   132  func (m *machineTestBuilder) setTimeout(timeout time.Duration) *machineTestBuilder {
   133  	m.timeout = timeout
   134  	return m
   135  }
   136  
   137  // toQemuInspectInfo is only for inspecting qemu machines.  Other providers will need
   138  // to make their own.
   139  func (mb *machineTestBuilder) toQemuInspectInfo() ([]qemuMachineInspectInfo, int, error) {
   140  	args := []string{"machine", "inspect"}
   141  	args = append(args, mb.names...)
   142  	session, err := runWrapper(mb.podmanBinary, args, defaultTimeout, true)
   143  	if err != nil {
   144  		return nil, -1, err
   145  	}
   146  	mii := []qemuMachineInspectInfo{}
   147  	err = json.Unmarshal(session.Bytes(), &mii)
   148  	return mii, session.ExitCode(), err
   149  }
   150  
   151  func (m *machineTestBuilder) runWithoutWait() (*machineSession, error) {
   152  	return runWrapper(m.podmanBinary, m.cmd, m.timeout, false)
   153  }
   154  
   155  func (m *machineTestBuilder) run() (*machineSession, error) {
   156  	return runWrapper(m.podmanBinary, m.cmd, m.timeout, true)
   157  }
   158  
   159  func runWrapper(podmanBinary string, cmdArgs []string, timeout time.Duration, wait bool) (*machineSession, error) {
   160  	if len(os.Getenv("DEBUG")) > 0 {
   161  		cmdArgs = append([]string{"--log-level=debug"}, cmdArgs...)
   162  	}
   163  	fmt.Println(podmanBinary + " " + strings.Join(cmdArgs, " "))
   164  	c := exec.Command(podmanBinary, cmdArgs...)
   165  	session, err := Start(c, GinkgoWriter, GinkgoWriter)
   166  	if err != nil {
   167  		Fail(fmt.Sprintf("Unable to start session: %q", err))
   168  		return nil, err
   169  	}
   170  	ms := machineSession{session}
   171  	if wait {
   172  		ms.waitWithTimeout(timeout)
   173  		fmt.Println("output:", ms.outputToString())
   174  	}
   175  	return &ms, nil
   176  }
   177  
   178  func (m *machineTestBuilder) init() {}
   179  
   180  // randomString returns a string of given length composed of random characters
   181  func randomString(n int) string {
   182  	var randomLetters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
   183  	b := make([]rune, n)
   184  	for i := range b {
   185  		b[i] = randomLetters[rand.Intn(len(randomLetters))]
   186  	}
   187  	return string(b)
   188  }